Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions src/core/shape/vertex.js
Original file line number Diff line number Diff line change
Expand Up @@ -992,4 +992,56 @@ p5.prototype.vertex = function(x, y, moveTo, u, v) {
return this;
};

/**
* Sets the 3d vertex normal to use for subsequent vertices drawn with
* <a href="#/p5/vertex">vertex()</a>. A normal is a vector that is generally
* nearly perpendicular to a shape's surface which controls how much light will
* be reflected from that part of the surface.
*
* @method normal
* @param {Vector} vector A p5.Vector representing the vertex normal.
* @chainable
* @example
* <div>
* <code>
* function setup() {
* createCanvas(100, 100, WEBGL);
* noStroke();
* }
*
* function draw() {
* background(255);
* rotateY(frameCount / 100);
* normalMaterial();
* beginShape(TRIANGLE_STRIP);
* normal(-0.4, 0.4, 0.8);
* vertex(-30, 30, 0);
*
* normal(0, 0, 1);
* vertex(-30, -30, 30);
* vertex(30, 30, 30);
*
* normal(0.4, -0.4, 0.8);
* vertex(30, -30, 0);
* endShape();
* }
* </code>
* </div>
*/

/**
* @method normal
* @param {Number} x The x component of the vertex normal.
* @param {Number} y The y component of the vertex normal.
* @param {Number} z The z component of the vertex normal.
* @chainable
*/
p5.prototype.normal = function(x, y, z) {
this._assert3d('normal');
p5._validateParameters('normal', arguments);
this._renderer.normal(...arguments);

return this;
};

export default p5;
36 changes: 23 additions & 13 deletions src/webgl/p5.RendererGL.Immediate.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ p5.RendererGL.prototype.vertex = function(x, y) {
}
const vert = new p5.Vector(x, y, z);
this.immediateMode.geometry.vertices.push(vert);
this.immediateMode.geometry.vertexNormals.push(this._currentNormal);
const vertexColor = this.curFillColor || [0.5, 0.5, 0.5, 1.0];
this.immediateMode.geometry.vertexColors.push(
vertexColor[0],
Expand Down Expand Up @@ -103,6 +104,28 @@ p5.RendererGL.prototype.vertex = function(x, y) {
return this;
};

/**
* Sets the normal to use for subsequent vertices.
* @method vertexNormal
* @param {Number} x
* @param {Number} y
* @param {Number} z
* @chainable
*
* @method vertexNormal
* @param {Vector} v
* @chainable
*/
p5.RendererGL.prototype.normal = function(xorv, y, z) {
if (xorv instanceof p5.Vector) {
this._currentNormal = xorv;
} else {
this._currentNormal = new p5.Vector(xorv, y, z);
}

return this;
};

/**
* End shape drawing and render vertices to screen.
* @chainable
Expand Down Expand Up @@ -251,7 +274,6 @@ p5.RendererGL.prototype._drawImmediateFill = function() {
const gl = this.GL;
const shader = this._getImmediateFillShader();

this._calculateNormals(this.immediateMode.geometry);
this._setFillUniforms(shader);

for (const buff of this.immediateMode.buffers.fill) {
Expand Down Expand Up @@ -298,16 +320,4 @@ p5.RendererGL.prototype._drawImmediateStroke = function() {
shader.unbindShader();
};

/**
* Called from _drawImmediateFill(). Currently adds default normals which
* only work for flat shapes.
* @parem
* @private
*/
p5.RendererGL.prototype._calculateNormals = function(geometry) {
geometry.vertices.forEach(() => {
geometry.vertexNormals.push(new p5.Vector(0, 0, 1));
});
};

export default p5.RendererGL;
5 changes: 5 additions & 0 deletions src/webgl/p5.RendererGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ p5.RendererGL = function(elt, pInst, isMainCanvas, attr) {
this.uPMatrix = new p5.Matrix();
this.uNMatrix = new p5.Matrix('mat3');

// Current vertex normal
this._currentNormal = new p5.Vector(0, 0, 1);

// Camera
this._curCamera = new p5.Camera(this);
this._curCamera._computeCameraDefaultSettings();
Expand Down Expand Up @@ -1026,6 +1029,8 @@ p5.RendererGL.prototype.push = function() {
properties._tex = this._tex;
properties.drawMode = this.drawMode;

properties._currentNormal = this._currentNormal;

return style;
};

Expand Down
54 changes: 54 additions & 0 deletions test/unit/webgl/normal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
suite('', function() {
var myp5;

if (!window.Modernizr.webgl) {
return;
}

setup(function() {
myp5 = new p5(function(p) {
p.setup = function() {
p.createCanvas(100, 100, p.WEBGL);
};
});
});

teardown(function() {
myp5.remove();
});

suite('p5.prototype.normal', function() {
test('should be a function', function() {
assert.ok(myp5.normal);
assert.typeOf(myp5.normal, 'function');
});
test('missing param #1', function() {
assert.validationError(function() {
myp5.normal(10);
});
});
test('wrong param type at #0', function() {
assert.validationError(function() {
myp5.normal('a', 1);
});
});
test('accepts numeric arguments', function() {
assert.doesNotThrow(
function() {
myp5.normal(0, 1, 0);
},
Error,
'got unwanted exception'
);
});
test('accepts vector argument', function() {
assert.doesNotThrow(
function() {
myp5.normal(myp5.createVector(0, 1, 0));
},
Error,
'got unwanted exception'
);
});
});
});