Skip to content

Commit a8d05e1

Browse files
authored
Merge pull request #7267 from davepagurek/shader-hooks-2.0
Shader hooks for dev-2.0
2 parents 989ebdd + ff9eebc commit a8d05e1

File tree

14 files changed

+1651
-113
lines changed

14 files changed

+1651
-113
lines changed

src/webgl/material.js

Lines changed: 857 additions & 2 deletions
Large diffs are not rendered by default.

src/webgl/p5.RendererGL.js

Lines changed: 152 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,7 +1714,7 @@ p5.RendererGL = class RendererGL extends Renderer {
17141714
sphereMapping
17151715
);
17161716
}
1717-
this.uNMatrix.inverseTranspose(this.uMVMatrix);
1717+
this.uNMatrix.inverseTranspose(this.uViewMatrix);
17181718
this.uNMatrix.invert3x3(this.uNMatrix);
17191719
this.sphereMapping.setUniform('uFovY', this._curCamera.cameraFOV);
17201720
this.sphereMapping.setUniform('uAspect', this._curCamera.aspectRatio);
@@ -1785,6 +1785,15 @@ p5.RendererGL = class RendererGL extends Renderer {
17851785
return this._getImmediateLineShader();
17861786
}
17871787

1788+
materialShader() {
1789+
if (!this._pInst._glAttributes.perPixelLighting) {
1790+
throw new Error(
1791+
'The material shader does not support hooks without perPixelLighting. Try turning it back on.'
1792+
);
1793+
}
1794+
return this._getLightShader();
1795+
}
1796+
17881797
_getLightShader() {
17891798
if (!this._defaultLightShader) {
17901799
if (this._pInst._glAttributes.perPixelLighting) {
@@ -1793,7 +1802,34 @@ p5.RendererGL = class RendererGL extends Renderer {
17931802
this._webGL2CompatibilityPrefix('vert', 'highp') +
17941803
defaultShaders.phongVert,
17951804
this._webGL2CompatibilityPrefix('frag', 'highp') +
1796-
defaultShaders.phongFrag
1805+
defaultShaders.phongFrag,
1806+
{
1807+
vertex: {
1808+
'void beforeVertex': '() {}',
1809+
'vec3 getLocalPosition': '(vec3 position) { return position; }',
1810+
'vec3 getWorldPosition': '(vec3 position) { return position; }',
1811+
'vec3 getLocalNormal': '(vec3 normal) { return normal; }',
1812+
'vec3 getWorldNormal': '(vec3 normal) { return normal; }',
1813+
'vec2 getUV': '(vec2 uv) { return uv; }',
1814+
'vec4 getVertexColor': '(vec4 color) { return color; }',
1815+
'void afterVertex': '() {}'
1816+
},
1817+
fragment: {
1818+
'void beforeFragment': '() {}',
1819+
'Inputs getPixelInputs': '(Inputs inputs) { return inputs; }',
1820+
'vec4 combineColors': `(ColorComponents components) {
1821+
vec4 color = vec4(0.);
1822+
color.rgb += components.diffuse * components.baseColor;
1823+
color.rgb += components.ambient * components.ambientColor;
1824+
color.rgb += components.specular * components.specularColor;
1825+
color.rgb += components.emissive;
1826+
color.a = components.opacity;
1827+
return color;
1828+
}`,
1829+
'vec4 getFinalColor': '(vec4 color) { return color; }',
1830+
'void afterFragment': '() {}'
1831+
}
1832+
}
17971833
);
17981834
} else {
17991835
this._defaultLightShader = new p5.Shader(
@@ -1823,55 +1859,163 @@ p5.RendererGL = class RendererGL extends Renderer {
18231859
return this._defaultImmediateModeShader;
18241860
}
18251861

1862+
normalShader() {
1863+
return this._getNormalShader();
1864+
}
1865+
18261866
_getNormalShader() {
18271867
if (!this._defaultNormalShader) {
18281868
this._defaultNormalShader = new p5.Shader(
18291869
this,
18301870
this._webGL2CompatibilityPrefix('vert', 'mediump') +
18311871
defaultShaders.normalVert,
18321872
this._webGL2CompatibilityPrefix('frag', 'mediump') +
1833-
defaultShaders.normalFrag
1873+
defaultShaders.normalFrag,
1874+
{
1875+
vertex: {
1876+
'void beforeVertex': '() {}',
1877+
'vec3 getLocalPosition': '(vec3 position) { return position; }',
1878+
'vec3 getWorldPosition': '(vec3 position) { return position; }',
1879+
'vec3 getLocalNormal': '(vec3 normal) { return normal; }',
1880+
'vec3 getWorldNormal': '(vec3 normal) { return normal; }',
1881+
'vec2 getUV': '(vec2 uv) { return uv; }',
1882+
'vec4 getVertexColor': '(vec4 color) { return color; }',
1883+
'void afterVertex': '() {}'
1884+
},
1885+
fragment: {
1886+
'void beforeFragment': '() {}',
1887+
'vec4 getFinalColor': '(vec4 color) { return color; }',
1888+
'void afterFragment': '() {}'
1889+
}
1890+
}
18341891
);
18351892
}
18361893

18371894
return this._defaultNormalShader;
18381895
}
18391896

1897+
colorShader() {
1898+
return this._getColorShader();
1899+
}
1900+
18401901
_getColorShader() {
18411902
if (!this._defaultColorShader) {
18421903
this._defaultColorShader = new p5.Shader(
18431904
this,
18441905
this._webGL2CompatibilityPrefix('vert', 'mediump') +
18451906
defaultShaders.normalVert,
18461907
this._webGL2CompatibilityPrefix('frag', 'mediump') +
1847-
defaultShaders.basicFrag
1908+
defaultShaders.basicFrag,
1909+
{
1910+
vertex: {
1911+
'void beforeVertex': '() {}',
1912+
'vec3 getLocalPosition': '(vec3 position) { return position; }',
1913+
'vec3 getWorldPosition': '(vec3 position) { return position; }',
1914+
'vec3 getLocalNormal': '(vec3 normal) { return normal; }',
1915+
'vec3 getWorldNormal': '(vec3 normal) { return normal; }',
1916+
'vec2 getUV': '(vec2 uv) { return uv; }',
1917+
'vec4 getVertexColor': '(vec4 color) { return color; }',
1918+
'void afterVertex': '() {}'
1919+
},
1920+
fragment: {
1921+
'void beforeFragment': '() {}',
1922+
'vec4 getFinalColor': '(vec4 color) { return color; }',
1923+
'void afterFragment': '() {}'
1924+
}
1925+
}
18481926
);
18491927
}
18501928

18511929
return this._defaultColorShader;
18521930
}
18531931

1932+
/**
1933+
* TODO(dave): un-private this when there is a way to actually override the
1934+
* shader used for points
1935+
*
1936+
* Get the shader used when drawing points with <a href="#/p5/point">`point()`</a>.
1937+
*
1938+
* You can call <a href="#/p5.Shader/modify">`pointShader().modify()`</a>
1939+
* and change any of the following hooks:
1940+
* - `void beforeVertex`: Called at the start of the vertex shader.
1941+
* - `vec3 getLocalPosition`: Update the position of vertices before transforms are applied. It takes in `vec3 position` and must return a modified version.
1942+
* - `vec3 getWorldPosition`: Update the position of vertices after transforms are applied. It takes in `vec3 position` and pust return a modified version.
1943+
* - `float getPointSize`: Update the size of the point. It takes in `float size` and must return a modified version.
1944+
* - `void afterVertex`: Called at the end of the vertex shader.
1945+
* - `void beforeFragment`: Called at the start of the fragment shader.
1946+
* - `bool shouldDiscard`: Points are drawn inside a square, with the corners discarded in the fragment shader to create a circle. Use this to change this logic. It takes in a `bool willDiscard` and must return a modified version.
1947+
* - `vec4 getFinalColor`: Update the final color after mixing. It takes in a `vec4 color` and must return a modified version.
1948+
* - `void afterFragment`: Called at the end of the fragment shader.
1949+
*
1950+
* Call `pointShader().inspectHooks()` to see all the possible hooks and
1951+
* their default implementations.
1952+
*
1953+
* @returns {p5.Shader} The `point()` shader
1954+
* @private()
1955+
*/
1956+
pointShader() {
1957+
return this._getPointShader();
1958+
}
1959+
18541960
_getPointShader() {
18551961
if (!this._defaultPointShader) {
18561962
this._defaultPointShader = new p5.Shader(
18571963
this,
18581964
this._webGL2CompatibilityPrefix('vert', 'mediump') +
18591965
defaultShaders.pointVert,
18601966
this._webGL2CompatibilityPrefix('frag', 'mediump') +
1861-
defaultShaders.pointFrag
1967+
defaultShaders.pointFrag,
1968+
{
1969+
vertex: {
1970+
'void beforeVertex': '() {}',
1971+
'vec3 getLocalPosition': '(vec3 position) { return position; }',
1972+
'vec3 getWorldPosition': '(vec3 position) { return position; }',
1973+
'float getPointSize': '(float size) { return size; }',
1974+
'void afterVertex': '() {}'
1975+
},
1976+
fragment: {
1977+
'void beforeFragment': '() {}',
1978+
'vec4 getFinalColor': '(vec4 color) { return color; }',
1979+
'bool shouldDiscard': '(bool outside) { return outside; }',
1980+
'void afterFragment': '() {}'
1981+
}
1982+
}
18621983
);
18631984
}
18641985
return this._defaultPointShader;
18651986
}
18661987

1988+
strokeShader() {
1989+
return this._getLineShader();
1990+
}
1991+
18671992
_getLineShader() {
18681993
if (!this._defaultLineShader) {
18691994
this._defaultLineShader = new p5.Shader(
18701995
this,
18711996
this._webGL2CompatibilityPrefix('vert', 'mediump') +
18721997
defaultShaders.lineVert,
18731998
this._webGL2CompatibilityPrefix('frag', 'mediump') +
1874-
defaultShaders.lineFrag
1999+
defaultShaders.lineFrag,
2000+
{
2001+
vertex: {
2002+
'void beforeVertex': '() {}',
2003+
'vec3 getLocalPosition': '(vec3 position) { return position; }',
2004+
'vec3 getWorldPosition': '(vec3 position) { return position; }',
2005+
'float getStrokeWeight': '(float weight) { return weight; }',
2006+
'vec2 getLineCenter': '(vec2 center) { return center; }',
2007+
'vec2 getLinePosition': '(vec2 position) { return position; }',
2008+
'vec4 getVertexColor': '(vec4 color) { return color; }',
2009+
'void afterVertex': '() {}'
2010+
},
2011+
fragment: {
2012+
'void beforeFragment': '() {}',
2013+
'Inputs getPixelInputs': '(Inputs inputs) { return inputs; }',
2014+
'vec4 getFinalColor': '(vec4 color) { return color; }',
2015+
'bool shouldDiscard': '(bool outside) { return outside; }',
2016+
'void afterFragment': '() {}'
2017+
}
2018+
}
18752019
);
18762020
}
18772021

@@ -2088,7 +2232,7 @@ p5.RendererGL = class RendererGL extends Renderer {
20882232
fillShader.setUniform('uSpecular', this._useSpecularMaterial);
20892233
fillShader.setUniform('uEmissive', this._useEmissiveMaterial);
20902234
fillShader.setUniform('uShininess', this._useShininess);
2091-
fillShader.setUniform('metallic', this._useMetalness);
2235+
fillShader.setUniform('uMetallic', this._useMetalness);
20922236

20932237
this._setImageLightUniforms(fillShader);
20942238

@@ -2161,14 +2305,7 @@ p5.RendererGL = class RendererGL extends Renderer {
21612305
let diffusedLight = this.getDiffusedTexture(this.activeImageLight);
21622306
shader.setUniform('environmentMapDiffused', diffusedLight);
21632307
let specularLight = this.getSpecularTexture(this.activeImageLight);
2164-
// In p5js the range of shininess is >= 1,
2165-
// Therefore roughness range will be ([0,1]*8)*20 or [0, 160]
2166-
// The factor of 8 is because currently the getSpecularTexture
2167-
// only calculated 8 different levels of roughness
2168-
// The factor of 20 is just to spread up this range so that,
2169-
// [1, max] of shininess is converted to [0,160] of roughness
2170-
let roughness = 20 / this._useShininess;
2171-
shader.setUniform('levelOfDetail', roughness * 8);
2308+
21722309
shader.setUniform('environmentMapSpecular', specularLight);
21732310
}
21742311
}

0 commit comments

Comments
 (0)