` to see your
-renderer online from anywhere. Add this link to your README.
-
-## Submit
-
-1. Open a GitHub pull request so that we can see that you have finished.
- The title should be "Submission: YOUR NAME".
- * **ADDITIONALLY:**
- In the body of the pull request, include a link to your repository.
-2. Send an email to the TA (gmail: kainino1+cis565@) with:
- * **Subject**: in the form of `[CIS565] Project N: PENNKEY`.
- * Direct link to your pull request on GitHub.
- * Estimate the amount of time you spent on the project.
- * If there were any outstanding problems, briefly explain.
- * **List the extra features you did.**
- * Feedback on the project itself, if any.
-
-### Third-Party Code Policy
-
-* Use of any third-party code must be approved by asking on our mailing list.
-* If it is approved, all students are welcome to use it. Generally, we approve
- use of third-party code that is not a core part of the project. For example,
- for the path tracer, we would approve using a third-party library for loading
- models, but would not approve copying and pasting a CUDA function for doing
- refraction.
-* Third-party code **MUST** be credited in README.md.
-* Using third-party code without its approval, including using another
- student's code, is an academic integrity violation, and will, at minimum,
- result in you receiving an F for the semester.
diff --git a/glsl/copy.frag.glsl b/glsl/copy.frag.glsl
index 0f5f8f7..aeef93f 100644
--- a/glsl/copy.frag.glsl
+++ b/glsl/copy.frag.glsl
@@ -5,11 +5,28 @@ precision highp int;
uniform sampler2D u_colmap;
uniform sampler2D u_normap;
+uniform float u_material;
varying vec3 v_position;
varying vec3 v_normal;
varying vec2 v_uv;
+
+vec3 applyNormalMap(vec3 geomnor, vec3 normap) {
+ normap = normap * 2.0 - 1.0;
+ vec3 up = normalize(vec3(0.001, 1, 0.001));
+ vec3 surftan = normalize(cross(geomnor, up));
+ vec3 surfbinor = cross(geomnor, surftan);
+ return normap.y * surftan + normap.x * surfbinor + normap.z * geomnor;
+}
+
+
void main() {
// TODO: copy values into gl_FragData[0], [1], etc.
+ gl_FragData[0] = vec4(v_position, 1.0);
+ vec4 gnorm = vec4(normalize(v_normal), 0.0);
+ gl_FragData[2] = texture2D(u_colmap, v_uv);
+ vec4 norm = texture2D(u_normap, v_uv);
+ gl_FragData[1].xyz = applyNormalMap(vec3(gnorm), vec3(norm));
+ gl_FragData[1].w = u_material;
}
diff --git a/glsl/deferred/ambient.frag.glsl b/glsl/deferred/ambient.frag.glsl
index 1fd4647..94e8ccf 100644
--- a/glsl/deferred/ambient.frag.glsl
+++ b/glsl/deferred/ambient.frag.glsl
@@ -3,25 +3,29 @@
precision highp float;
precision highp int;
-#define NUM_GBUFFERS 4
+#define NUM_GBUFFERS 3
uniform sampler2D u_gbufs[NUM_GBUFFERS];
uniform sampler2D u_depth;
varying vec2 v_uv;
+
void main() {
vec4 gb0 = texture2D(u_gbufs[0], v_uv);
vec4 gb1 = texture2D(u_gbufs[1], v_uv);
vec4 gb2 = texture2D(u_gbufs[2], v_uv);
- vec4 gb3 = texture2D(u_gbufs[3], v_uv);
float depth = texture2D(u_depth, v_uv).x;
+ float amb = .2;
// TODO: Extract needed properties from the g-buffers into local variables
+ vec3 pos = gb0.xyz;
+ vec3 colmap = gb2.xyz;
+ vec3 nor = gb1.xyz;
if (depth == 1.0) {
gl_FragColor = vec4(0, 0, 0, 0); // set alpha to 0
return;
}
- gl_FragColor = vec4(0.1, 0.1, 0.1, 1); // TODO: replace this
+ gl_FragColor = vec4(amb * colmap, 1); // TODO: replace this
}
diff --git a/glsl/deferred/blinnphong-pointlight.frag.glsl b/glsl/deferred/blinnphong-pointlight.frag.glsl
index b24a54a..9fe8cee 100644
--- a/glsl/deferred/blinnphong-pointlight.frag.glsl
+++ b/glsl/deferred/blinnphong-pointlight.frag.glsl
@@ -2,38 +2,86 @@
precision highp float;
precision highp int;
-#define NUM_GBUFFERS 4
+#define NUM_GBUFFERS 3
uniform vec3 u_lightCol;
uniform vec3 u_lightPos;
uniform float u_lightRad;
uniform sampler2D u_gbufs[NUM_GBUFFERS];
uniform sampler2D u_depth;
+uniform vec3 u_cameraPos;
+uniform float u_toon;
+//uniform float u_width;
+//uniform float u_height;
varying vec2 v_uv;
-vec3 applyNormalMap(vec3 geomnor, vec3 normap) {
- normap = normap * 2.0 - 1.0;
- vec3 up = normalize(vec3(0.001, 1, 0.001));
- vec3 surftan = normalize(cross(geomnor, up));
- vec3 surfbinor = cross(geomnor, surftan);
- return normap.y * surftan + normap.x * surfbinor + normap.z * geomnor;
-}
+
void main() {
vec4 gb0 = texture2D(u_gbufs[0], v_uv);
vec4 gb1 = texture2D(u_gbufs[1], v_uv);
vec4 gb2 = texture2D(u_gbufs[2], v_uv);
- vec4 gb3 = texture2D(u_gbufs[3], v_uv);
+
float depth = texture2D(u_depth, v_uv).x;
+
+
// TODO: Extract needed properties from the g-buffers into local variables
+ vec3 pos = gb0.xyz;
+
+ vec3 colmap = gb2.xyz;
+ float spec = gb1.w;
+
+
+ vec3 normal = normalize(gb1.xyz);
+ vec3 lightDir = normalize((u_lightPos - pos)); // / length(u_lightPos - pos);
- // If nothing was rendered to this pixel, set alpha to 0 so that the
- // postprocessing step can render the sky color.
- if (depth == 1.0) {
- gl_FragColor = vec4(0, 0, 0, 0);
+ if (length(u_lightPos - pos) > u_lightRad) {
+ gl_FragColor = vec4(0, 0, 0, 1.0);
return;
+ }
+ float lambertian = min(max(dot(lightDir,normal), 0.0), 1.0);
+ float specular = 0.0;
+
+ vec3 viewDir = normalize(u_cameraPos - pos);
+ vec3 halfDir = normalize(lightDir + viewDir);
+ float specAngle = max(dot(halfDir, normal), 0.0);
+
+
+ specular = pow(specAngle, spec);
+
+
+ vec3 color = lambertian * colmap * u_lightCol * (u_lightRad - length(u_lightPos - pos)) + specular*vec3(1.0);
+
+ if (u_toon > 0.5) {
+ //diffuse values
+ if (lambertian < 0.5) {
+ lambertian = .2;
+ }
+ else {
+ lambertian = 1.0;
+ }
+
+ //specular highlight
+ if (specAngle > .75) {
+ specular = pow(1.0, spec);
+ }
+ else {
+ specular = 0.0;
+ }
+
+ //fade from center of light
+ float fade;
+ if (u_lightRad - length(u_lightPos - pos) < .5) fade = .25;
+ else fade = .75;
+
+ //check silhouette
+
+ color = lambertian * colmap * u_lightCol * fade + specular*vec3(1.0);
}
- gl_FragColor = vec4(0, 0, 1, 1); // TODO: perform lighting calculations
+
+
+ gl_FragColor = vec4(color, 1.0);
+
}
diff --git a/glsl/deferred/debug.frag.glsl b/glsl/deferred/debug.frag.glsl
index d05638c..d028687 100644
--- a/glsl/deferred/debug.frag.glsl
+++ b/glsl/deferred/debug.frag.glsl
@@ -2,49 +2,49 @@
precision highp float;
precision highp int;
-#define NUM_GBUFFERS 4
+#define NUM_GBUFFERS 3
uniform int u_debug;
uniform sampler2D u_gbufs[NUM_GBUFFERS];
uniform sampler2D u_depth;
-
+uniform mat4 u_prevPM;
varying vec2 v_uv;
+uniform vec3 u_cameraPos;
const vec4 SKY_COLOR = vec4(0.66, 0.73, 1.0, 1.0);
-vec3 applyNormalMap(vec3 geomnor, vec3 normap) {
- normap = normap * 2.0 - 1.0;
- vec3 up = normalize(vec3(0.001, 1, 0.001));
- vec3 surftan = normalize(cross(geomnor, up));
- vec3 surfbinor = cross(geomnor, surftan);
- return normap.y * surftan + normap.x * surfbinor + normap.z * geomnor;
-}
void main() {
vec4 gb0 = texture2D(u_gbufs[0], v_uv);
vec4 gb1 = texture2D(u_gbufs[1], v_uv);
vec4 gb2 = texture2D(u_gbufs[2], v_uv);
- vec4 gb3 = texture2D(u_gbufs[3], v_uv);
+
float depth = texture2D(u_depth, v_uv).x;
// TODO: Extract needed properties from the g-buffers into local variables
- vec3 pos;
- vec3 geomnor;
- vec3 colmap;
- vec3 normap;
- vec3 nor;
+ vec3 pos = gb0.xyz;
+
+ vec3 colmap = gb2.xyz;
+
+ vec3 nor = gb1.xyz;
+
+
+ vec4 H = vec4(v_uv.x*2.0 - 1.0, (v_uv.y) * 2.0 - 1.0, depth, 1.0);
+ vec4 currentPos = H;
+ vec4 prevPos = u_prevPM * vec4(pos / gb0.w, 1.0);
+ prevPos /= prevPos.w;
+
+ vec2 velocity = ((currentPos.xy) - prevPos.xy) / 2.0;
if (u_debug == 0) {
gl_FragColor = vec4(vec3(depth), 1.0);
} else if (u_debug == 1) {
gl_FragColor = vec4(abs(pos) * 0.1, 1.0);
} else if (u_debug == 2) {
- gl_FragColor = vec4(abs(geomnor), 1.0);
+ gl_FragColor = vec4(abs(nor), 1.0);
} else if (u_debug == 3) {
gl_FragColor = vec4(colmap, 1.0);
} else if (u_debug == 4) {
- gl_FragColor = vec4(normap, 1.0);
- } else if (u_debug == 5) {
- gl_FragColor = vec4(abs(nor), 1.0);
+ gl_FragColor = vec4(abs(velocity), 0.0, 1.0);
} else {
gl_FragColor = vec4(1, 0, 1, 1);
}
diff --git a/glsl/post/blend.frag.glsl b/glsl/post/blend.frag.glsl
new file mode 100644
index 0000000..c98f530
--- /dev/null
+++ b/glsl/post/blend.frag.glsl
@@ -0,0 +1,23 @@
+#version 100
+precision highp float;
+precision highp int;
+
+
+varying vec2 v_uv;
+
+uniform sampler2D scene;
+uniform sampler2D bloomBlur;
+uniform float exposure;
+
+void main()
+{
+ const float gamma = 2.2;
+ vec3 hdrColor = texture(scene, v_uv).rgb;
+ vec3 bloomColor = texture(bloomBlur, v_uv).rgb;
+ hdrColor += bloomColor; // additive blending
+ // tone mapping
+ vec3 result = vec3(1.0) - exp(-hdrColor * exposure);
+ // also gamma correct while we're at it
+ result = pow(result, vec3(1.0 / gamma));
+ gl_FragColor = vec4(result, 1.0f);
+}
\ No newline at end of file
diff --git a/glsl/post/bloom.frag.glsl b/glsl/post/bloom.frag.glsl
new file mode 100644
index 0000000..8f9a668
--- /dev/null
+++ b/glsl/post/bloom.frag.glsl
@@ -0,0 +1,64 @@
+#version 100
+precision highp float;
+precision highp int;
+
+uniform sampler2D u_color;
+uniform float u_bloom;
+varying vec2 v_uv;
+
+uniform vec2 u_resolution;
+uniform vec2 u_dir;
+
+const vec4 SKY_COLOR = vec4(0.01, 0.14, 0.42, 1.0);
+
+void main() {
+ vec4 color = texture2D(u_color, v_uv);
+
+ if (color.a == 0.0) {
+ gl_FragColor = SKY_COLOR;
+ return;
+ }
+
+
+ vec4 sum = vec4(0.0);
+
+ //the amount to blur, i.e. how far off center to sample from
+ //1.0 -> blur by one pixel
+ //2.0 -> blur by two pixels, etc.
+ float blur = 4.0/u_resolution.x;
+
+ //the direction of our blur
+ //(1.0, 0.0) -> x-axis blur
+ //(0.0, 1.0) -> y-axis blur
+ float hstep = u_dir.x;
+ float vstep = u_dir.y;
+
+
+
+ //apply blurring, using a 9-tap filter with predefined gaussian weights
+
+ sum += texture2D(u_color, vec2(v_uv.x - 4.0*blur*hstep, v_uv.y - 4.0*blur*vstep)) * 0.0162162162;
+ sum += texture2D(u_color, vec2(v_uv.x - 3.0*blur*hstep, v_uv.y - 3.0*blur*vstep)) * 0.0540540541;
+ sum += texture2D(u_color, vec2(v_uv.x - 2.0*blur*hstep, v_uv.y - 2.0*blur*vstep)) * 0.1216216216;
+ sum += texture2D(u_color, vec2(v_uv.x - 1.0*blur*hstep, v_uv.y - 1.0*blur*vstep)) * 0.1945945946;
+
+ sum += texture2D(u_color, vec2(v_uv.x, v_uv.y)) * 0.2270270270;
+
+ sum += texture2D(u_color, vec2(v_uv.x + 1.0*blur*hstep, v_uv.y + 1.0*blur*vstep)) * 0.1945945946;
+ sum += texture2D(u_color, vec2(v_uv.x + 2.0*blur*hstep, v_uv.y + 2.0*blur*vstep)) * 0.1216216216;
+ sum += texture2D(u_color, vec2(v_uv.x + 3.0*blur*hstep, v_uv.y + 3.0*blur*vstep)) * 0.0540540541;
+ sum += texture2D(u_color, vec2(v_uv.x + 4.0*blur*hstep, v_uv.y + 4.0*blur*vstep)) * 0.0162162162;
+
+ //discard alpha for our simple demo, multiply by vertex color and return
+ gl_FragColor = color + color * sum;
+
+
+
+}
+
+
+
+
+
+
+
diff --git a/glsl/post/bloom1.frag.glsl b/glsl/post/bloom1.frag.glsl
new file mode 100644
index 0000000..eea8f7e
--- /dev/null
+++ b/glsl/post/bloom1.frag.glsl
@@ -0,0 +1,63 @@
+#version 100
+precision highp float;
+precision highp int;
+
+uniform sampler2D u_color;
+uniform float u_bloom;
+varying vec2 v_uv;
+
+uniform vec2 u_resolution;
+uniform vec2 u_dir;
+
+const vec4 SKY_COLOR = vec4(0.01, 0.14, 0.42, 1.0);
+
+void main() {
+ vec4 color = texture2D(u_color, v_uv);
+
+ if (color.a == 0.0) {
+ gl_FragColor = SKY_COLOR;
+ return;
+ }
+
+
+ vec4 sum = vec4(0.0);
+
+ //the amount to blur, i.e. how far off center to sample from
+ //1.0 -> blur by one pixel
+ //2.0 -> blur by two pixels, etc.
+ float blur = 4.0/u_resolution.x;
+
+ //the direction of our blur
+ //(1.0, 0.0) -> x-axis blur
+ //(0.0, 1.0) -> y-axis blur
+ float hstep = u_dir.x;
+ float vstep = u_dir.y;
+
+ //apply blurring, using a 9-tap filter with predefined gaussian weights
+
+ sum += texture2D(u_color, vec2(v_uv.x - 4.0*blur*hstep, v_uv.y - 4.0*blur*vstep)) * 0.0162162162;
+ sum += texture2D(u_color, vec2(v_uv.x - 3.0*blur*hstep, v_uv.y - 3.0*blur*vstep)) * 0.0540540541;
+ sum += texture2D(u_color, vec2(v_uv.x - 2.0*blur*hstep, v_uv.y - 2.0*blur*vstep)) * 0.1216216216;
+ sum += texture2D(u_color, vec2(v_uv.x - 1.0*blur*hstep, v_uv.y - 1.0*blur*vstep)) * 0.1945945946;
+
+ sum += texture2D(u_color, vec2(v_uv.x, v_uv.y)) * 0.2270270270;
+
+ sum += texture2D(u_color, vec2(v_uv.x + 1.0*blur*hstep, v_uv.y + 1.0*blur*vstep)) * 0.1945945946;
+ sum += texture2D(u_color, vec2(v_uv.x + 2.0*blur*hstep, v_uv.y + 2.0*blur*vstep)) * 0.1216216216;
+ sum += texture2D(u_color, vec2(v_uv.x + 3.0*blur*hstep, v_uv.y + 3.0*blur*vstep)) * 0.0540540541;
+ sum += texture2D(u_color, vec2(v_uv.x + 4.0*blur*hstep, v_uv.y + 4.0*blur*vstep)) * 0.0162162162;
+
+ //discard alpha for our simple demo, multiply by vertex color and return
+ gl_FragColor = color * vec4(sum.rgb, 1.0);
+
+
+
+
+}
+
+
+
+
+
+
+
diff --git a/glsl/post/motion.frag.glsl b/glsl/post/motion.frag.glsl
new file mode 100644
index 0000000..1755d19
--- /dev/null
+++ b/glsl/post/motion.frag.glsl
@@ -0,0 +1,63 @@
+#version 100
+precision highp float;
+precision highp int;
+
+uniform sampler2D u_color;
+
+varying vec2 v_uv;
+
+#define NUM_GBUFFERS 4
+uniform mat4 u_prevPM;
+uniform mat4 u_invMat;
+uniform sampler2D u_depth;
+uniform sampler2D u_worldPos;
+
+
+const vec4 SKY_COLOR = vec4(0.01, 0.14, 0.42, 1.0);
+
+void main() {
+ vec4 color = texture2D(u_color, v_uv);
+ vec2 texCoords = v_uv;
+ float depth = texture2D(u_depth, v_uv).x;
+ vec4 gb0 = texture2D(u_worldPos, v_uv);
+ vec3 pos = gb0.xyz; // / gb0.w;
+ vec4 H = vec4(v_uv.x*2.0 - 1.0, (v_uv.y) * 2.0 - 1.0, depth, 1.0);
+ //vec4 D = u_invMat * H;
+ //D = D / D.w;
+ vec4 currentPos = H;
+
+ vec4 prevPos = (u_prevPM) * vec4(pos, 1.0);
+ prevPos /= prevPos.w;
+
+ vec2 velocity = (currentPos.xy - prevPos.xy) / 2.0;
+
+ texCoords += velocity;
+
+ for (int i = 0; i < 5; i++) {
+ vec4 currentCol = texture2D(u_color, texCoords);
+ color += currentCol;
+ texCoords += velocity;
+ }
+
+ gl_FragColor = (color / 5.0);
+
+ /*
+ vec4 prevPos = u_prevPM * vec4(pos, 1.0);
+ prevPos.xyz /= prevPos.w;
+ prevPos.xy = prevPos.xy * 0.5 + 0.5;
+
+ vec2 blurVec = prevPos.xy - v_uv;
+
+ vec4 result = texture2D(u_color, v_uv);
+ for (int i = 1; i < 5; ++i) {
+
+ vec2 offset = blurVec * (float(i) / float(5.0 - 1.0) - 0.5);
+
+
+ result += texture2D(u_color, v_uv + offset);
+ }
+
+ result /= 5.0;
+
+ gl_FragColor = result;*/
+}
\ No newline at end of file
diff --git a/glsl/post/one.frag.glsl b/glsl/post/one.frag.glsl
index 94191cd..fb2b181 100644
--- a/glsl/post/one.frag.glsl
+++ b/glsl/post/one.frag.glsl
@@ -3,8 +3,9 @@ precision highp float;
precision highp int;
uniform sampler2D u_color;
-
+uniform float u_bloom;
varying vec2 v_uv;
+uniform float u_dir;
const vec4 SKY_COLOR = vec4(0.01, 0.14, 0.42, 1.0);
@@ -16,5 +17,6 @@ void main() {
return;
}
+
gl_FragColor = color;
}
diff --git a/glsl/post/toon.frag.glsl b/glsl/post/toon.frag.glsl
new file mode 100644
index 0000000..d2d029c
--- /dev/null
+++ b/glsl/post/toon.frag.glsl
@@ -0,0 +1,43 @@
+#version 100
+precision highp float;
+precision highp int;
+
+uniform sampler2D u_color;
+uniform float u_bloom;
+varying vec2 v_uv;
+
+uniform vec2 u_resolution;
+
+const vec4 SKY_COLOR = vec4(0.01, 0.14, 0.42, 1.0);
+
+void main() {
+ vec4 color = texture2D(u_color, v_uv);
+
+ if (color.a == 0.0) {
+ gl_FragColor = SKY_COLOR;
+ return;
+ }
+
+
+ vec4 neighbor1 = texture2D(u_color, vec2(v_uv.x, v_uv.y - 1.0 / u_resolution.y));
+ vec4 neighbor2 = texture2D(u_color, vec2(v_uv.x - 1.0 / u_resolution.x, v_uv.y - 1.0 / u_resolution.y));
+ vec4 neighbor3 = texture2D(u_color, vec2(v_uv.x + 1.0 / u_resolution.x, v_uv.y - 1.0 / u_resolution.y));
+ vec4 neighbor4 = texture2D(u_color, vec2(v_uv.x, v_uv.y + 1.0 / u_resolution.y));
+ vec4 neighbor5 = texture2D(u_color, vec2(v_uv.x - 1.0 / u_resolution.x, v_uv.y + 1.0 / u_resolution.y));
+ vec4 neighbor6 = texture2D(u_color, vec2(v_uv.x + 1.0 / u_resolution.x, v_uv.y + 1.0 / u_resolution.y));
+
+ // Blend and perform edge ramping
+ vec4 neighbors1 = (neighbor1 + neighbor2 + neighbor3) - (neighbor4 + neighbor5 + neighbor6);
+ neighbors1 = vec4(vec3(max(max(neighbors1.x, neighbors1.y), neighbors1.z)), 1.0);
+ vec4 neighbors2 = -(neighbor1 + neighbor2 + neighbor3) + (neighbor4 + neighbor5 + neighbor6);
+ neighbors2 = vec4(vec3(max(max(neighbors2.x, neighbors2.y), neighbors2.z)), 1.0);
+ vec4 outline;
+ if(neighbors1.x > 0.2 || neighbors2.x > .2) {
+ outline = vec4(0.0);
+ }
+ else {
+ outline = vec4(vec3(1.0), 0.0);
+ }
+
+ gl_FragColor = (outline) * color;
+}
\ No newline at end of file
diff --git a/glsl/red.frag.glsl b/glsl/red.frag.glsl
index f8ef1ec..a6188fe 100644
--- a/glsl/red.frag.glsl
+++ b/glsl/red.frag.glsl
@@ -3,5 +3,5 @@ precision highp float;
precision highp int;
void main() {
- gl_FragColor = vec4(1, 0, 0, 1);
+ gl_FragColor = vec4(0.1, 0.1, 0.1, 1);
}
diff --git a/img/Bloom.png b/img/Bloom.png
new file mode 100644
index 0000000..22cb021
Binary files /dev/null and b/img/Bloom.png differ
diff --git a/img/FinalVideo.mov b/img/FinalVideo.mov
new file mode 100644
index 0000000..6a53f70
Binary files /dev/null and b/img/FinalVideo.mov differ
diff --git a/img/backwards_toon.png b/img/backwards_toon.png
new file mode 100644
index 0000000..5806957
Binary files /dev/null and b/img/backwards_toon.png differ
diff --git a/img/badScissor.png b/img/badScissor.png
new file mode 100644
index 0000000..1a87ed5
Binary files /dev/null and b/img/badScissor.png differ
diff --git a/img/diff_specExp.png b/img/diff_specExp.png
new file mode 100644
index 0000000..d5039e6
Binary files /dev/null and b/img/diff_specExp.png differ
diff --git a/img/final_noEffects.png b/img/final_noEffects.png
new file mode 100644
index 0000000..95f0d9b
Binary files /dev/null and b/img/final_noEffects.png differ
diff --git a/img/goodScissor.png b/img/goodScissor.png
new file mode 100644
index 0000000..ccf0d55
Binary files /dev/null and b/img/goodScissor.png differ
diff --git a/img/graph.png b/img/graph.png
new file mode 100644
index 0000000..2111aed
Binary files /dev/null and b/img/graph.png differ
diff --git a/img/light_badScissor.png b/img/light_badScissor.png
new file mode 100644
index 0000000..6e2718a
Binary files /dev/null and b/img/light_badScissor.png differ
diff --git a/img/light_goodScissor.png b/img/light_goodScissor.png
new file mode 100644
index 0000000..3435fc6
Binary files /dev/null and b/img/light_goodScissor.png differ
diff --git a/img/motionBlur_trim.mov b/img/motionBlur_trim.mov
new file mode 100644
index 0000000..b7b30e3
Binary files /dev/null and b/img/motionBlur_trim.mov differ
diff --git a/img/motion_blur.gif b/img/motion_blur.gif
new file mode 100644
index 0000000..02013ff
Binary files /dev/null and b/img/motion_blur.gif differ
diff --git a/img/motion_blur.mov b/img/motion_blur.mov
new file mode 100644
index 0000000..fb8ddd2
Binary files /dev/null and b/img/motion_blur.mov differ
diff --git a/img/notEvenCloseMotion.png b/img/notEvenCloseMotion.png
new file mode 100644
index 0000000..9071071
Binary files /dev/null and b/img/notEvenCloseMotion.png differ
diff --git a/img/toon1.png b/img/toon1.png
new file mode 100644
index 0000000..8c9cd0b
Binary files /dev/null and b/img/toon1.png differ
diff --git a/img/toon_noOutline.png b/img/toon_noOutline.png
new file mode 100644
index 0000000..3f8d5ad
Binary files /dev/null and b/img/toon_noOutline.png differ
diff --git a/img/toon_withBox.png b/img/toon_withBox.png
new file mode 100644
index 0000000..48d2465
Binary files /dev/null and b/img/toon_withBox.png differ
diff --git a/index.html b/index.html
index 4a0ec13..ed3c0e5 100644
--- a/index.html
+++ b/index.html
@@ -79,9 +79,18 @@
height: 100%;
}
+ #msgbox {
+ font-family: sans-serif;
+ color: white;
+ height: 1.4em;
+ position: fixed;
+ bottom: 2em;
+ left: 0;
+ }
+
DEBUG MODE!
(Disable before measuring performance.)
diff --git a/js/deferredRender.js b/js/deferredRender.js
index 3d19a30..93494fb 100644
--- a/js/deferredRender.js
+++ b/js/deferredRender.js
@@ -1,6 +1,7 @@
(function() {
'use strict';
// deferredSetup.js must be loaded first
+ var prevMat;
R.deferredRender = function(state) {
if (!aborted && (
@@ -10,7 +11,10 @@
!R.prog_Ambient ||
!R.prog_BlinnPhong_PointLight ||
!R.prog_Debug ||
- !R.progPost1)) {
+ !R.progPost1 ||
+ !R.progToon ||
+ !R.progBloom ||
+ !R.progMotion)) {
console.log('waiting for programs to load...');
return;
}
@@ -28,12 +32,12 @@
// CHECKITOUT: START HERE! You can even uncomment this:
//debugger;
- { // TODO: this block should be removed after testing renderFullScreenQuad
+ /*{ // TODO: this block should be removed after testing renderFullScreenQuad
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
// TODO: Implement/test renderFullScreenQuad first
renderFullScreenQuad(R.progRed);
return;
- }
+ }*/
R.pass_copy.render(state);
@@ -41,14 +45,33 @@
// Do a debug render instead of a regular render
// Don't do any post-processing in debug mode
R.pass_debug.render(state);
- } else {
+ }
+ else if (cfg && cfg.bloom) {
+ R.pass_deferred.render(state);
+ //R.pass_post1.render(state);
+ R.pass_bloom.render(state);
+ R.pass_bloom2.render(state);
+ }
+ else if (cfg && cfg.toon) {
+ R.pass_deferred.render(state);
+ //R.pass_bloom1.render(state);
+ R.pass_toon.render(state);
+
+ }
+ else if (cfg && cfg.motion) {
+ R.pass_deferred.render(state);
+ R.pass_motion.render(state);
+ }
+ else {
// * Deferred pass and postprocessing pass(es)
// TODO: uncomment these
- //R.pass_deferred.render(state);
- //R.pass_post1.render(state);
+ R.pass_deferred.render(state);
+ R.pass_post1.render(state);
// OPTIONAL TODO: call more postprocessing passes, if any
}
+
+
};
/**
@@ -57,22 +80,24 @@
R.pass_copy.render = function(state) {
// * Bind the framebuffer R.pass_copy.fbo
// TODO: ^
-
+ gl.bindFramebuffer(gl.FRAMEBUFFER, R.pass_copy.fbo);
// * Clear screen using R.progClear
- TODO: renderFullScreenQuad(R.progClear);
+ renderFullScreenQuad(R.progClear);
// * Clear depth buffer to value 1.0 using gl.clearDepth and gl.clear
// TODO: ^
+ gl.clearDepth(1.0);
// TODO: ^
-
+ gl.clear(gl.DEPTH_BUFFER_BIT);
// * "Use" the program R.progCopy.prog
// TODO: ^
+ gl.useProgram(R.progCopy.prog);
// TODO: Write glsl/copy.frag.glsl
var m = state.cameraMat.elements;
// * Upload the camera matrix m to the uniform R.progCopy.u_cameraMat
// using gl.uniformMatrix4fv
// TODO: ^
-
+ gl.uniformMatrix4fv(R.progCopy.u_cameraMat, gl.FALSE, m);
// * Draw the scene
drawScene(state);
};
@@ -97,9 +122,19 @@
// * Tell shader which debug view to use
bindTexturesForLightPass(R.prog_Debug);
gl.uniform1i(R.prog_Debug.u_debug, cfg.debugView);
-
+ if (prevMat !== undefined) {
+ gl.uniformMatrix4fv(R.prog_Debug.u_prevPM, gl.FALSE, prevMat.elements);
+ }
+ gl.uniform3f(R.prog_Debug.u_cameraPos, state.cameraPos[0], state.cameraPos[1], state.cameraPos[2]);
// * Render a fullscreen quad to perform shading on
+
+
+ prevMat = state.cameraMat.clone();
+
+
+
renderFullScreenQuad(R.prog_Debug);
+
};
/**
@@ -117,20 +152,64 @@
// * _ADD_ together the result of each lighting pass
// Enable blending and use gl.blendFunc to blend with:
- // color = 1 * src_color + 1 * dst_color
+ gl.enable(gl.BLEND);
+ //color = 1 * src_color + 1 * dst_color
// TODO: ^
-
+ gl.blendFunc(1.0, 1.0);
// * Bind/setup the ambient pass, and render using fullscreen quad
bindTexturesForLightPass(R.prog_Ambient);
renderFullScreenQuad(R.prog_Ambient);
+ gl.enable(gl.SCISSOR_TEST);
// * Bind/setup the Blinn-Phong pass, and render using fullscreen quad
bindTexturesForLightPass(R.prog_BlinnPhong_PointLight);
// TODO: add a loop here, over the values in R.lights, which sets the
// uniforms R.prog_BlinnPhong_PointLight.u_lightPos/Col/Rad etc.,
// then does renderFullScreenQuad(R.prog_BlinnPhong_PointLight).
-
+
+ for(var i = 0; i < R.lights.length; i++) {
+
+ gl.uniform3fv(R.prog_BlinnPhong_PointLight.u_lightCol, R.lights[i].col);
+ gl.uniform3fv(R.prog_BlinnPhong_PointLight.u_lightPos, R.lights[i].pos);
+ gl.uniform1f(R.prog_BlinnPhong_PointLight.u_lightRad, R.lights[i].rad);
+ gl.uniform3f(R.prog_BlinnPhong_PointLight.u_cameraPos, state.cameraPos[0], state.cameraPos[1], state.cameraPos[2]);
+ if (cfg.toon) {
+ gl.uniform1f(R.prog_BlinnPhong_PointLight.u_toon, 1.0);
+ //gl.unifrom1f(R.prog_BlinnPhong_PointLight.u_width, width);
+ //gl.uniform1f(R.prog_BlinnPhong_PointLight.u_height, height);
+ //console.log('toon is true');
+ }
+ else {
+ gl.uniform1f(R.prog_BlinnPhong_PointLight.u_toon, 0.0);
+ //console.log('toon is false');
+ }
+ var sci = getImprovedScissorForLight(state.viewMat, state.projMat, R.lights[i]);
+ var sc = getScissorForLight(state.viewMat, state.projMat, R.lights[i])
+ if (sc && sci) {
+
+ if (cfg.debugScissor) {
+ gl.scissor(sc[0], sc[1], sc[2], sc[3]);
+ //console.log('scissor is true');
+ renderFullScreenQuad(R.progRed);
+ }
+ else if (cfg.debugImproveScissor) {
+ gl.scissor(sci[0], sci[1], sci[2], sci[3]);
+ renderFullScreenQuad(R.progRed);
+ }
+ else {
+ gl.scissor(sci[0], sci[1], sci[2], sci[3]);
+ //console.log('scissor is false');
+ renderFullScreenQuad(R.prog_BlinnPhong_PointLight);
+ }
+ }
+ /*else {
+ renderFullScreenQuad(R.prog_BlinnPhong_PointLight);
+ }*/
+ //renderFullScreenQuad(R.prog_BlinnPhong_PointLight);
+ }
+
+ gl.disable(gl.SCISSOR_TEST);
// TODO: In the lighting loop, use the scissor test optimization
// Enable gl.SCISSOR_TEST, render all lights, then disable it.
//
@@ -175,15 +254,125 @@
// * Bind the deferred pass's color output as a texture input
// Set gl.TEXTURE0 as the gl.activeTexture unit
// TODO: ^
+ gl.activeTexture(gl.TEXTURE0);
// Bind the TEXTURE_2D, R.pass_deferred.colorTex to the active texture unit
// TODO: ^
+ gl.bindTexture(gl.TEXTURE_2D, R.pass_deferred.colorTex);
// Configure the R.progPost1.u_color uniform to point at texture unit 0
gl.uniform1i(R.progPost1.u_color, 0);
-
+ if (cfg.bloom) {
+ gl.uniform1f(R.progPost1.u_bloom, 1.0);
+ gl.uniform1f(R.progPost1.u_dir, 1.0);
+
+
+ renderFullScreenQuad(R.progPost1);
+
+ //gl.uniform1f(R.progPost1.u_bloom, 1.0);
+
+ //gl.uniform1f(R.progPost1.u_bloom, 0.0);
+ //renderFullScreenQuad(R.progPost1);
+ }
+ else {
+ gl.uniform1f(R.progPost1.u_bloom, 0.0);
+
+ }
// * Render a fullscreen quad to perform shading on
renderFullScreenQuad(R.progPost1);
};
+ R.pass_toon.render = function(state) {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.clearDepth(1.0);
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+
+ // * Bind the postprocessing shader program
+ gl.useProgram(R.progToon.prog);
+ gl.activeTexture(gl.TEXTURE0);
+ // Bind the TEXTURE_2D, R.pass_deferred.colorTex to the active texture unit
+ // TODO: ^
+ gl.bindTexture(gl.TEXTURE_2D, R.pass_deferred.colorTex);
+ // Configure the R.progPost1.u_color uniform to point at texture unit 0
+ gl.uniform1i(R.progToon.u_color, 0);
+ gl.uniform2f(R.progToon.u_resolution, state.width, state.height);
+
+ renderFullScreenQuad(R.progToon);
+ }
+
+ R.pass_bloom.render = function(state) {
+ //gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.clearDepth(1.0);
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+
+ // * Bind the postprocessing shader program
+ gl.useProgram(R.progBloom.prog);
+ gl.activeTexture(gl.TEXTURE0);
+ // Bind the TEXTURE_2D, R.pass_deferred.colorTex to the active texture unit
+ // TODO: ^
+ gl.bindTexture(gl.TEXTURE_2D, R.pass_deferred.colorTex);
+ // Configure the R.progPost1.u_color uniform to point at texture unit 0
+ gl.uniform1i(R.progBloom.u_color, 0);
+ gl.uniform2f(R.progBloom.u_resolution, state.width, state.height);
+ gl.uniform2f(R.progBloom.u_dir, 1.0, 0.0);
+ renderFullScreenQuad(R.progBloom);
+ }
+
+ R.pass_bloom2.render = function(state) {
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.clearDepth(1.0);
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+
+ // * Bind the postprocessing shader program
+ gl.useProgram(R.progBloom.prog);
+ gl.activeTexture(gl.TEXTURE0);
+ // Bind the TEXTURE_2D, R.pass_deferred.colorTex to the active texture unit
+ // TODO: ^
+ gl.bindTexture(gl.TEXTURE_2D, R.pass_deferred.colorTex);
+ // Configure the R.progPost1.u_color uniform to point at texture unit 0
+ gl.uniform1i(R.progBloom.u_color, 0);
+ gl.uniform2f(R.progBloom.u_resolution, state.width, state.height);
+ gl.uniform2f(R.progBloom.u_dir, 0.0, 1.0);
+ renderFullScreenQuad(R.progBloom);
+ }
+
+ R.pass_motion.render = function(state) {
+
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+ gl.clearDepth(1.0);
+ gl.clear(gl.DEPTH_BUFFER_BIT);
+
+ // * Bind the postprocessing shader program
+ gl.useProgram(R.progMotion.prog);
+ gl.activeTexture(gl.TEXTURE0);
+ // Bind the TEXTURE_2D, R.pass_deferred.colorTex to the active texture unit
+ // TODO: ^
+ gl.bindTexture(gl.TEXTURE_2D, R.pass_deferred.colorTex);
+ // Configure the R.progPost1.u_color uniform to point at texture unit 0
+ gl.uniform1i(R.progMotion.u_color, 0);
+ gl.activeTexture(gl.TEXTURE1);
+ gl.bindTexture(gl.TEXTURE_2D, R.pass_copy.gbufs[0]);
+ gl.uniform1i(R.progMotion.u_worldPos, 1);
+
+ gl.activeTexture(gl.TEXTURE2);
+ gl.bindTexture(gl.TEXTURE_2D, R.pass_copy.depthTex);
+ gl.uniform1i(R.progMotion.u_depth, 2);
+
+ //gl.uniformMatrix4fv(R.progMotion.u_prevPM, gl.FALSE, state.projMat);
+ if (prevMat !== undefined) {
+ gl.uniformMatrix4fv(R.progMotion.u_prevPM, gl.FALSE, prevMat.elements);
+ }
+ var camMat = new THREE.Matrix4();
+ camMat = camMat.getInverse(state.cameraMat);
+
+ gl.uniform3f(R.progMotion.u_cameraPos, state.cameraPos[0], state.cameraPos[1], state.cameraPos[2]);
+ gl.uniformMatrix4fv(R.progMotion.u_invMat, gl.FALSE, camMat.elements);
+
+ prevMat = state.cameraMat.clone();
+
+ renderFullScreenQuad(R.progMotion);
+
+
+ }
+
var renderFullScreenQuad = (function() {
// The variables in this function are private to the implementation of
// renderFullScreenQuad. They work like static local variables in C++.
@@ -205,12 +394,14 @@
var init = function() {
// Create a new buffer with gl.createBuffer, and save it as vbo.
// TODO: ^
-
+ vbo = gl.createBuffer();
// Bind the VBO as the gl.ARRAY_BUFFER
// TODO: ^
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
// Upload the positions array to the currently-bound array buffer
// using gl.bufferData in static draw mode.
// TODO: ^
+ gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
};
return function(prog) {
@@ -224,15 +415,17 @@
// Bind the VBO as the gl.ARRAY_BUFFER
// TODO: ^
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
// Enable the bound buffer as the vertex attrib array for
// prog.a_position, using gl.enableVertexAttribArray
// TODO: ^
+ gl.enableVertexAttribArray(prog.a_position);
// Use gl.vertexAttribPointer to tell WebGL the type/layout of the buffer
// TODO: ^
-
+ gl.vertexAttribPointer(prog.a_position, 3, gl.FLOAT, gl.FALSE, 0 , 0);
// Use gl.drawArrays (or gl.drawElements) to draw your quad.
// TODO: ^
-
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
// Unbind the array buffer.
gl.bindBuffer(gl.ARRAY_BUFFER, null);
};
diff --git a/js/deferredSetup.js b/js/deferredSetup.js
index ca6baec..99a5187 100644
--- a/js/deferredSetup.js
+++ b/js/deferredSetup.js
@@ -6,9 +6,13 @@
R.pass_debug = {};
R.pass_deferred = {};
R.pass_post1 = {};
+ R.pass_toon = {};
+ R.pass_bloom = {};
+ R.pass_bloom2 = {};
+ R.pass_motion = {};
R.lights = [];
- R.NUM_GBUFFERS = 4;
+ R.NUM_GBUFFERS = 3;
/**
* Set up the deferred pipeline framebuffer objects and textures.
@@ -21,8 +25,8 @@
};
// TODO: Edit if you want to change the light initial positions
- R.light_min = [-6, 0, -14];
- R.light_max = [6, 18, 14];
+ R.light_min = [-14, 0, -6];
+ R.light_max = [14, 18, 6];
R.light_dt = -0.03;
R.LIGHT_RADIUS = 4.0;
R.NUM_LIGHTS = 20; // TODO: test with MORE lights!
@@ -34,14 +38,14 @@
for (var i = 0; i < 3; i++) {
var mn = R.light_min[i];
var mx = R.light_max[i];
- r = Math.random() * (mx - mn) + mn;
+ r[i] = Math.random() * (mx - mn) + mn;
}
return r;
};
for (var i = 0; i < R.NUM_LIGHTS; i++) {
R.lights.push({
- pos: [posfn(), posfn(), posfn()],
+ pos: posfn(),
col: [
1 + Math.random(),
1 + Math.random(),
@@ -110,7 +114,7 @@
p.a_position = gl.getAttribLocation(prog, 'a_position');
p.a_normal = gl.getAttribLocation(prog, 'a_normal');
p.a_uv = gl.getAttribLocation(prog, 'a_uv');
-
+ p.u_material = gl.getUniformLocation(prog, 'u_material');
// Save the object into this variable for access later
R.progCopy = p;
});
@@ -137,21 +141,49 @@
p.u_lightPos = gl.getUniformLocation(p.prog, 'u_lightPos');
p.u_lightCol = gl.getUniformLocation(p.prog, 'u_lightCol');
p.u_lightRad = gl.getUniformLocation(p.prog, 'u_lightRad');
+ p.u_cameraPos = gl.getUniformLocation(p.prog, 'u_cameraPos');
+ p.u_toon = gl.getUniformLocation(p.prog, 'u_toon');
R.prog_BlinnPhong_PointLight = p;
});
loadDeferredProgram('debug', function(p) {
p.u_debug = gl.getUniformLocation(p.prog, 'u_debug');
+ p.u_prevPM = gl.getUniformLocation(p.prog, 'u_prevPM');
+ p.u_cameraPos = gl.getUniformLocation(p.prog, 'u_cameraPos');
// Save the object into this variable for access later
R.prog_Debug = p;
});
loadPostProgram('one', function(p) {
p.u_color = gl.getUniformLocation(p.prog, 'u_color');
+ p.u_bloom = gl.getUniformLocation(p.prog, 'u_bloom');
+ p.u_dir = gl.getUniformLocation(p.prog, 'u_dir');
// Save the object into this variable for access later
R.progPost1 = p;
});
+ loadPostProgram('toon', function(p) {
+ p.u_color = gl.getUniformLocation(p.prog, 'u_color');
+ p.u_resolution = gl.getUniformLocation(p.prog, 'u_resolution');
+ R.progToon = p;
+ });
+
+ loadPostProgram('bloom', function(p) {
+ p.u_color = gl.getUniformLocation(p.prog, 'u_color');
+ p.u_resolution = gl.getUniformLocation(p.prog, 'u_resolution');
+ p.u_dir = gl.getUniformLocation(p.prog, 'u_dir');
+ R.progBloom = p;
+ });
+
+ loadPostProgram('motion', function(p) {
+ p.u_color = gl.getUniformLocation(p.prog, 'u_color');
+ p.u_prevPM = gl.getUniformLocation(p.prog,'u_prevPM');
+ p.u_invMat = gl.getUniformLocation(p.prog, 'u_invMat');
+ p.u_worldPos = gl.getUniformLocation(p.prog, 'u_worldPos');
+ p.u_depth = gl.getUniformLocation(p.prog, 'u_depth');
+ p.u_cameraPos = gl.getUniformLocation(p.prog, 'u_cameraPos');
+ R.progMotion = p;
+ })
// TODO: If you add more passes, load and set up their shader programs.
};
diff --git a/js/framework.js b/js/framework.js
index a0653a5..52649a2 100644
--- a/js/framework.js
+++ b/js/framework.js
@@ -17,16 +17,20 @@ var width, height;
cameraMat: cameraMat,
projMat: camera.projectionMatrix,
viewMat: camera.matrixWorldInverse,
- models: models
+ cameraPos: camera.position,
+ models: models,
+ width: width,
+ height: height
});
};
var update = function() {
controls.update();
+ stats.end();
stats.begin();
render();
- gl.finish();
- stats.end();
+ //gl.finish();
+ //stats.end();
if (!aborted) {
requestAnimationFrame(update);
}
@@ -88,7 +92,8 @@ var width, height;
initExtensions();
stats = new Stats();
- stats.setMode(1); // 0: fps, 1: ms, 2: mb
+ stats.setMode(0);
+ //stats.setMode(1); // 0: fps, 1: ms, 2: mb
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
@@ -133,6 +138,21 @@ var width, height;
loadTexture('models/sponza/normal.png').then(function(tex) {
m.normap = tex;
});
+ m.material = 100000.0;
+ models.push(m);
+ });
+ });
+ loadModel('models/cube.obj', function(o) {
+ scene.add(o);
+ uploadModel(o, function(m) {
+ // CHECKITOUT: load textures
+ loadTexture('models/cow_color.jpg').then(function(tex) {
+ m.colmap = tex;
+ });
+ loadTexture('models/cow_norm.png').then(function(tex) {
+ m.normap = tex;
+ });
+ m.material = 1.0;
models.push(m);
});
});
@@ -200,7 +220,7 @@ var width, height;
elemCount: idx.length,
position: gposition,
normal: gnormal,
- uv: guv
+ uv: guv,
};
if (callback) {
diff --git a/js/ui.js b/js/ui.js
index 05c1852..cc4eb57 100644
--- a/js/ui.js
+++ b/js/ui.js
@@ -7,7 +7,10 @@ var cfg;
// TODO: Define config fields and defaults here
this.debugView = -1;
this.debugScissor = false;
- this.enableEffect0 = false;
+ this.debugImproveScissor = false;
+ this.toon = false;
+ this.bloom = false;
+ this.motion = false;
};
var init = function() {
@@ -19,15 +22,17 @@ var cfg;
'None': -1,
'0 Depth': 0,
'1 Position': 1,
- '2 Geometry normal': 2,
+ '2 Surface normal': 2,
'3 Color map': 3,
- '4 Normal map': 4,
- '5 Surface normal': 5
+ '4 Velocity' : 4,
});
gui.add(cfg, 'debugScissor');
+ gui.add(cfg, 'debugImproveScissor');
var eff0 = gui.addFolder('EFFECT NAME HERE');
- eff0.add(cfg, 'enableEffect0');
+ eff0.add(cfg, 'toon');
+ eff0.add(cfg, 'bloom');
+ eff0.add(cfg, 'motion');
// TODO: add more effects toggles and parameters here
};
diff --git a/js/util.js b/js/util.js
index 762fb4a..64c7dd1 100644
--- a/js/util.js
+++ b/js/util.js
@@ -83,7 +83,9 @@ window.loadModel = function(obj, callback) {
var onProgress = function(xhr) {
if (xhr.lengthComputable) {
var percentComplete = xhr.loaded / xhr.total * 100;
- console.log(Math.round(percentComplete, 2) + '% downloaded');
+ var msg = obj + ': ' + Math.round(percentComplete, 2) + '% loaded';
+ console.log(msg);
+ $('#msgbox').text(msg);
}
};
@@ -108,6 +110,9 @@ window.readyModelForDraw = function(prog, m) {
gl.bindTexture(gl.TEXTURE_2D, m.normap);
gl.uniform1i(prog.u_normap, 1);
}
+ if (m.material !== undefined) {
+ gl.uniform1f(prog.u_material, m.material);
+ }
gl.enableVertexAttribArray(prog.a_position);
gl.bindBuffer(gl.ARRAY_BUFFER, m.position);
@@ -179,6 +184,82 @@ window.getScissorForLight = (function() {
};
})();
+window.getImprovedScissorForLight = (function() {
+ // Pre-allocate for performance - avoids additional allocation
+ var a = new THREE.Vector4(0, 0, 0, 0);
+ var b = new THREE.Vector4(0, 0, 0, 0);
+ var c = new THREE.Vector4(0, 0, 0, 0);
+ var d = new THREE.Vector4(0, 0, 0, 0);
+ var minpt = new THREE.Vector2(0, 0);
+ var minpt2 = new THREE.Vector2(0, 0);
+ var maxpt = new THREE.Vector2(0, 0);
+ var maxpt2 = new THREE.Vector2(0, 0);
+ var ret = [0, 0, 0, 0];
+
+ return function(view, proj, l) {
+ // front bottom-left corner of sphere's bounding cube
+ a.fromArray(l.pos);
+ a.w = 1;
+ a.applyMatrix4(view);
+ a.x -= l.rad;
+ a.y -= l.rad;
+ a.z -= l.rad;
+ a.applyMatrix4(proj);
+ a.divideScalar(a.w);
+
+ // front upper-right corner of sphere's bounding cube
+ b.fromArray(l.pos);
+ b.w = 1;
+ b.applyMatrix4(view);
+ b.x += l.rad;
+ b.y += l.rad;
+ b.z += l.rad;
+ b.applyMatrix4(proj);
+ b.divideScalar(b.w);
+
+ //back bottom-left corner of sphere's bounding cube
+ /*c.fromArray(l.pos);
+ c.w = 1;
+ c.x -= l.rad;
+ c.y -= l.rad;
+ c.z -= l.rad;
+ c.applyMatrix4(proj);
+ c.divideScalar(c.w);
+
+ //back upper-right corner of sphere's bounding cube
+ d.fromArray(l.pos);
+ d.w = 1;
+ d.applyMatrix4(view);
+ d.x += l.rad;
+ d.y += l.rad;
+ d.z -= l.rad;
+ d.applyMatrix4(proj);
+ d.divideScalar(d.w);*/
+
+ minpt.set(Math.max(-1, a.x), Math.max(-1, a.y));
+ //minpt2.set(Math.max(-1, c.x), Math.max(-1, c.y));
+ maxpt.set(Math.min( 1, b.x), Math.min( 1, b.y));
+ //maxpt2.set(Math.min(1, d.x), Math.min(1, d.y));
+
+ //minpt.set(Math.min(a.x, c.x), Math.min(a.y, c.y));
+ //maxpt.set(Math.max(b.x, d.x), Math.max(b.y, d.y));
+
+ if (maxpt.x < -1 || 1 < minpt.x ||
+ maxpt.y < -1 || 1 < minpt.y) {
+ return null;
+ }
+
+ minpt.addScalar(1.0); minpt.multiplyScalar(0.5);
+ maxpt.addScalar(1.0); maxpt.multiplyScalar(0.5);
+
+ ret[0] = Math.round(width * minpt.x);
+ ret[1] = Math.round(height * minpt.y);
+ ret[2] = Math.round(width * (maxpt.x - minpt.x));
+ ret[3] = Math.round(height * (maxpt.y - minpt.y));
+ return ret;
+ };
+})();
+
window.abortIfFramebufferIncomplete = function(fbo) {
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
var fbstatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
diff --git a/lib/three.js b/lib/three.js
index fea1dc1..dd98045 100644
--- a/lib/three.js
+++ b/lib/three.js
@@ -11743,6 +11743,7 @@ THREE.Camera = function () {
this.matrixWorldInverse = new THREE.Matrix4();
this.projectionMatrix = new THREE.Matrix4();
+ this.prevProjMatrix = new THREE.Matrix4();
};
@@ -11793,7 +11794,7 @@ THREE.Camera.prototype.copy = function ( source ) {
this.matrixWorldInverse.copy( source.matrixWorldInverse );
this.projectionMatrix.copy( source.projectionMatrix );
-
+ this.prevProjMatrix.copy(source.prevProjMatrix);
return this;
};
@@ -11915,7 +11916,7 @@ THREE.OrthographicCamera.prototype = Object.create( THREE.Camera.prototype );
THREE.OrthographicCamera.prototype.constructor = THREE.OrthographicCamera;
THREE.OrthographicCamera.prototype.updateProjectionMatrix = function () {
-
+ this.prevProjMatrix = this.projectionMatrix;
var dx = ( this.right - this.left ) / ( 2 * this.zoom );
var dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
var cx = ( this.right + this.left ) / 2;
@@ -12058,7 +12059,7 @@ THREE.PerspectiveCamera.prototype.updateProjectionMatrix = function () {
var fov = THREE.Math.radToDeg( 2 * Math.atan( Math.tan( THREE.Math.degToRad( this.fov ) * 0.5 ) / this.zoom ) );
if ( this.fullWidth ) {
-
+ this.prevProjMatrix = this.projectionMatrix;
var aspect = this.fullWidth / this.fullHeight;
var top = Math.tan( THREE.Math.degToRad( fov * 0.5 ) ) * this.near;
var bottom = - top;
@@ -12077,7 +12078,7 @@ THREE.PerspectiveCamera.prototype.updateProjectionMatrix = function () {
);
} else {
-
+ this.prevProjMatrix = this.projectionMatrix;
this.projectionMatrix.makePerspective( fov, this.aspect, this.near, this.far );
}
diff --git a/models/cow.jpg b/models/cow.jpg
new file mode 100644
index 0000000..f6a23aa
Binary files /dev/null and b/models/cow.jpg differ
diff --git a/models/cow_color.jpg b/models/cow_color.jpg
new file mode 100644
index 0000000..90cee2c
Binary files /dev/null and b/models/cow_color.jpg differ
diff --git a/models/cow_norm.png b/models/cow_norm.png
new file mode 100644
index 0000000..50e44a2
Binary files /dev/null and b/models/cow_norm.png differ
diff --git a/models/green.jpg b/models/green.jpg
new file mode 100644
index 0000000..1d8cbda
Binary files /dev/null and b/models/green.jpg differ