Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature implementation: emissiveMaterial() #3820

Merged
merged 11 commits into from
Jul 3, 2019
3 changes: 2 additions & 1 deletion developer_docs/webgl_mode_architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ Provides flat shading of objects, based on the current fill color.
#### Light Shader (for lighting AND textures)
Accounts for:
* Lighting parameters set by `ambientLight()`, `directionalLight()`, and `pointLight()`
* Material parameters set by `ambientMaterial()`, and `specularMaterial()`
* Material parameters set by `ambientMaterial()`, `emissiveMaterial()` and `specularMaterial()`
* Texture parameters, set by `texture()`

#### Normal Shader
Expand Down Expand Up @@ -133,6 +133,7 @@ The normal shader is set when `normalMaterial()` is in use. It uses the surface
|`uniform vec3 uPointLightLocation[8];`| |x | | | |
|`uniform vec3 uPointLightColor[8];` | |x | | | |
|`uniform bool uSpecular;` | |x | | | |
|`uniform bool uEmissive;` | |x | | | |
|`uniform int uShininess;` | |x | | | |
|`uniform bool uUseLighting;` | |x | | | |
|`uniform float uConstantAttenuation;` | |x | | | |
Expand Down
56 changes: 56 additions & 0 deletions src/webgl/material.js
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ p5.prototype.normalMaterial = function() {
p5._validateParameters('normalMaterial', arguments);
this._renderer.drawMode = constants.FILL;
this._renderer._useSpecularMaterial = false;
this._renderer._useEmissiveMaterial = false;
this._renderer._useNormalMaterial = true;
this._renderer.curFillColor = [1, 1, 1, 1];
this._renderer._setProperty('_doFill', true);
Expand Down Expand Up @@ -409,6 +410,7 @@ p5.prototype.texture = function(tex) {

this._renderer.drawMode = constants.TEXTURE;
this._renderer._useSpecularMaterial = false;
this._renderer._useEmissiveMaterial = false;
this._renderer._useNormalMaterial = false;
this._renderer._tex = tex;
this._renderer._setProperty('_doFill', true);
Expand Down Expand Up @@ -613,6 +615,59 @@ p5.prototype.ambientMaterial = function(v1, v2, v3, a) {
var color = p5.prototype.color.apply(this, arguments);
this._renderer.curFillColor = color._array;
this._renderer._useSpecularMaterial = false;
this._renderer._useEmissiveMaterial = false;
this._renderer._useNormalMaterial = false;
this._renderer._enableLighting = true;
this._renderer._tex = null;

return this;
};

/**
* Sets the emissive color of the material used for geometry drawn to
* the screen. This is a misnomer in the sense that the material does not
* actually emit light that effects surrounding polygons. Instead,
* it gives the appearance that the object is glowing. An emissive material
* will display at full strength even if there is no light for it to reflect.
* @method emissiveMaterial
* @param {Number} v1 gray value, red or hue value
* (depending on the current color mode),
* @param {Number} [v2] green or saturation value
* @param {Number} [v3] blue or brightness value
* @param {Number} [a] opacity
* @chainable
* @example
* <div>
* <code>
* function setup() {
* createCanvas(100, 100, WEBGL);
* }
* function draw() {
* background(0);
* noStroke();
* ambientLight(0);
* emissiveMaterial(130, 230, 0);
* sphere(40);
* }
* </code>
* </div>
*
* @alt
* radiating light source from top right of canvas
*/
/**
* @method emissiveMaterial
* @param {Number[]|String|p5.Color} color color, color Array, or CSS color string
* @chainable
*/
p5.prototype.emissiveMaterial = function(v1, v2, v3, a) {
this._assert3d('emissiveMaterial');
p5._validateParameters('emissiveMaterial', arguments);

var color = p5.prototype.color.apply(this, arguments);
this._renderer.curFillColor = color._array;
this._renderer._useSpecularMaterial = false;
this._renderer._useEmissiveMaterial = true;
this._renderer._useNormalMaterial = false;
this._renderer._enableLighting = true;
this._renderer._tex = null;
Expand Down Expand Up @@ -664,6 +719,7 @@ p5.prototype.specularMaterial = function(v1, v2, v3, a) {
var color = p5.prototype.color.apply(this, arguments);
this._renderer.curFillColor = color._array;
this._renderer._useSpecularMaterial = true;
this._renderer._useEmissiveMaterial = false;
this._renderer._useNormalMaterial = false;
this._renderer._enableLighting = true;
this._renderer._tex = null;
Expand Down
3 changes: 3 additions & 0 deletions src/webgl/p5.RendererGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ p5.RendererGL = function(elt, pInst, isMainCanvas, attr) {
this.blendExt = this.GL.getExtension('EXT_blend_minmax');

this._useSpecularMaterial = false;
this._useEmissiveMaterial = false;
this._useNormalMaterial = false;
this._useShininess = 1;

Expand Down Expand Up @@ -874,6 +875,7 @@ p5.RendererGL.prototype.push = function() {
properties.curFillColor = this.curFillColor;

properties._useSpecularMaterial = this._useSpecularMaterial;
properties._useEmissiveMaterial = this._useEmissiveMaterial;
properties._useShininess = this._useShininess;

properties.constantAttenuation = this.constantAttenuation;
Expand Down Expand Up @@ -1112,6 +1114,7 @@ p5.RendererGL.prototype._setFillUniforms = function(fillShader) {
fillShader.setUniform('uTint', this._tint);

fillShader.setUniform('uSpecular', this._useSpecularMaterial);
fillShader.setUniform('uEmissive', this._useEmissiveMaterial);
fillShader.setUniform('uShininess', this._useShininess);

fillShader.setUniform('uUseLighting', this._enableLighting);
Expand Down
10 changes: 8 additions & 2 deletions src/webgl/shaders/light_texture.frag
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ uniform vec4 uMaterialColor;
uniform vec4 uTint;
uniform sampler2D uSampler;
uniform bool isTexture;
uniform bool uEmissive;

varying highp vec2 vVertTexCoord;
varying vec3 vDiffuseColor;
varying vec3 vSpecularColor;

void main(void) {
gl_FragColor = isTexture ? texture2D(uSampler, vVertTexCoord) * (uTint / vec4(255, 255, 255, 255)) : uMaterialColor;
gl_FragColor.rgb = gl_FragColor.rgb * vDiffuseColor + vSpecularColor;
if(uEmissive && !isTexture) {
gl_FragColor = uMaterialColor;
}
else {
gl_FragColor = isTexture ? texture2D(uSampler, vVertTexCoord) * (uTint / vec4(255, 255, 255, 255)) : uMaterialColor;
gl_FragColor.rgb = gl_FragColor.rgb * vDiffuseColor + vSpecularColor;
}
}
10 changes: 8 additions & 2 deletions src/webgl/shaders/phong.frag
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
uniform vec4 uMaterialColor;
uniform sampler2D uSampler;
uniform bool isTexture;
uniform bool uEmissive;

varying vec3 vNormal;
varying vec2 vTexCoord;
Expand All @@ -15,6 +16,11 @@ void main(void) {
vec3 specular;
totalLight(vViewPosition, normalize(vNormal), diffuse, specular);

gl_FragColor = isTexture ? texture2D(uSampler, vTexCoord) : uMaterialColor;
gl_FragColor.rgb = gl_FragColor.rgb * (diffuse + vAmbientColor) + specular;
if(uEmissive && !isTexture) {
gl_FragColor = uMaterialColor;
}
else {
gl_FragColor = isTexture ? texture2D(uSampler, vTexCoord) : uMaterialColor;
gl_FragColor.rgb = gl_FragColor.rgb * (diffuse + vAmbientColor) + specular;
}
}
17 changes: 17 additions & 0 deletions test/manual-test-examples/webgl/material/emissive/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="../../../styles.css">
<script language="javascript" type="text/javascript" src="../../../../../lib/p5.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
<script src="../../stats.js"></script>
</head>

<body>
</body>

</html>
32 changes: 32 additions & 0 deletions test/manual-test-examples/webgl/material/emissive/sketch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
// setAttributes('perPixelLighting', true);
}

function draw() {
background(0);

var locY = mouseY - height / 2;
var locX = mouseX - width / 2;

ambientLight(100);
pointLight(200, 200, 200, locX, locY, 0);

translate(-200, 0, 0);
push();
ambientMaterial(250);
rotateZ(frameCount * 0.02);
rotateX(frameCount * 0.02);
rotateY(frameCount * 0.02);
torus(80, 20, 64, 64);
pop();

translate(400, 0, 0);
push();
emissiveMaterial(200, 0, 0);
rotateZ(frameCount * 0.02);
rotateX(frameCount * 0.02);
rotateY(frameCount * 0.02);
torus(81, 20, 64, 64);
pop();
}
3 changes: 2 additions & 1 deletion test/unit/core/rendering.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ suite('Rendering', function() {
'ambientLight', 'directionalLight', 'pointLight', 'lights',
'model',
'createShader', 'shader',
'normalMaterial', 'texture', 'ambientMaterial', 'specularMaterial', 'shininess', 'lightFalloff',
'normalMaterial', 'texture', 'ambientMaterial', 'emissiveMaterial', 'specularMaterial',
'shininess', 'lightFalloff',
'plane', 'box', 'sphere', 'cylinder', 'cone', 'ellipsoid', 'torus',
];

Expand Down
17 changes: 17 additions & 0 deletions test/unit/webgl/p5.Shader.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ suite('p5.Shader', function() {
'uMaterialColor',
'uSampler',
'isTexture',
'uEmissive',
'uConstantAttenuation',
'uLinearAttenuation',
'uQuadraticAttenuation'
Expand Down Expand Up @@ -211,6 +212,22 @@ suite('p5.Shader', function() {
'after call to specularMaterial()'
);
});
test('Light shader set after emissiveMaterial()', function() {
var lightShader = myp5._renderer._getLightShader();
myp5.emissiveMaterial(128);
var selectedRetainedShader = myp5._renderer._getRetainedFillShader();
var selectedImmediateShader = myp5._renderer._getImmediateFillShader();
assert(
lightShader === selectedRetainedShader,
"_renderer's retain mode shader was not light shader " +
'after call to emissiveMaterial()'
);
assert(
lightShader === selectedImmediateShader,
"_renderer's immediate mode shader was not light shader " +
'after call to emissiveMaterial()'
);
});

test('Able to setUniform empty arrays', function() {
myp5.shader(myp5._renderer._getLightShader());
Expand Down