Skip to content

Commit 5042087

Browse files
authored
Merge pull request #7149 from davepagurek/shader-hooks
Shader hooks
2 parents 9a3dc91 + 6f24ac5 commit 5042087

File tree

15 files changed

+338799
-112
lines changed

15 files changed

+338799
-112
lines changed

docs/data.json

Lines changed: 337147 additions & 0 deletions
Large diffs are not rendered by default.

src/webgl/material.js

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

src/webgl/p5.RendererGL.js

Lines changed: 151 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,6 +1798,15 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
17981798
return this._getImmediateLineShader();
17991799
}
18001800

1801+
materialShader() {
1802+
if (!this._pInst._glAttributes.perPixelLighting) {
1803+
throw new Error(
1804+
'The material shader does not support hooks without perPixelLighting. Try turning it back on.'
1805+
);
1806+
}
1807+
return this._getLightShader();
1808+
}
1809+
18011810
_getLightShader() {
18021811
if (!this._defaultLightShader) {
18031812
if (this._pInst._glAttributes.perPixelLighting) {
@@ -1806,7 +1815,34 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
18061815
this._webGL2CompatibilityPrefix('vert', 'highp') +
18071816
defaultShaders.phongVert,
18081817
this._webGL2CompatibilityPrefix('frag', 'highp') +
1809-
defaultShaders.phongFrag
1818+
defaultShaders.phongFrag,
1819+
{
1820+
vertex: {
1821+
'void beforeVertex': '() {}',
1822+
'vec3 getLocalPosition': '(vec3 position) { return position; }',
1823+
'vec3 getWorldPosition': '(vec3 position) { return position; }',
1824+
'vec3 getLocalNormal': '(vec3 normal) { return normal; }',
1825+
'vec3 getWorldNormal': '(vec3 normal) { return normal; }',
1826+
'vec2 getUV': '(vec2 uv) { return uv; }',
1827+
'vec4 getVertexColor': '(vec4 color) { return color; }',
1828+
'void afterVertex': '() {}'
1829+
},
1830+
fragment: {
1831+
'void beforeFragment': '() {}',
1832+
'Inputs getPixelInputs': '(Inputs inputs) { return inputs; }',
1833+
'vec4 combineColors': `(ColorComponents components) {
1834+
vec4 color = vec4(0.);
1835+
color.rgb += components.diffuse * components.baseColor;
1836+
color.rgb += components.ambient * components.ambientColor;
1837+
color.rgb += components.specular * components.specularColor;
1838+
color.rgb += components.emissive;
1839+
color.a = components.opacity;
1840+
return color;
1841+
}`,
1842+
'vec4 getFinalColor': '(vec4 color) { return color; }',
1843+
'void afterFragment': '() {}'
1844+
}
1845+
}
18101846
);
18111847
} else {
18121848
this._defaultLightShader = new p5.Shader(
@@ -1836,55 +1872,163 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
18361872
return this._defaultImmediateModeShader;
18371873
}
18381874

1875+
normalShader() {
1876+
return this._getNormalShader();
1877+
}
1878+
18391879
_getNormalShader() {
18401880
if (!this._defaultNormalShader) {
18411881
this._defaultNormalShader = new p5.Shader(
18421882
this,
18431883
this._webGL2CompatibilityPrefix('vert', 'mediump') +
18441884
defaultShaders.normalVert,
18451885
this._webGL2CompatibilityPrefix('frag', 'mediump') +
1846-
defaultShaders.normalFrag
1886+
defaultShaders.normalFrag,
1887+
{
1888+
vertex: {
1889+
'void beforeVertex': '() {}',
1890+
'vec3 getLocalPosition': '(vec3 position) { return position; }',
1891+
'vec3 getWorldPosition': '(vec3 position) { return position; }',
1892+
'vec3 getLocalNormal': '(vec3 normal) { return normal; }',
1893+
'vec3 getWorldNormal': '(vec3 normal) { return normal; }',
1894+
'vec2 getUV': '(vec2 uv) { return uv; }',
1895+
'vec4 getVertexColor': '(vec4 color) { return color; }',
1896+
'void afterVertex': '() {}'
1897+
},
1898+
fragment: {
1899+
'void beforeFragment': '() {}',
1900+
'vec4 getFinalColor': '(vec4 color) { return color; }',
1901+
'void afterFragment': '() {}'
1902+
}
1903+
}
18471904
);
18481905
}
18491906

18501907
return this._defaultNormalShader;
18511908
}
18521909

1910+
colorShader() {
1911+
return this._getColorShader();
1912+
}
1913+
18531914
_getColorShader() {
18541915
if (!this._defaultColorShader) {
18551916
this._defaultColorShader = new p5.Shader(
18561917
this,
18571918
this._webGL2CompatibilityPrefix('vert', 'mediump') +
18581919
defaultShaders.normalVert,
18591920
this._webGL2CompatibilityPrefix('frag', 'mediump') +
1860-
defaultShaders.basicFrag
1921+
defaultShaders.basicFrag,
1922+
{
1923+
vertex: {
1924+
'void beforeVertex': '() {}',
1925+
'vec3 getLocalPosition': '(vec3 position) { return position; }',
1926+
'vec3 getWorldPosition': '(vec3 position) { return position; }',
1927+
'vec3 getLocalNormal': '(vec3 normal) { return normal; }',
1928+
'vec3 getWorldNormal': '(vec3 normal) { return normal; }',
1929+
'vec2 getUV': '(vec2 uv) { return uv; }',
1930+
'vec4 getVertexColor': '(vec4 color) { return color; }',
1931+
'void afterVertex': '() {}'
1932+
},
1933+
fragment: {
1934+
'void beforeFragment': '() {}',
1935+
'vec4 getFinalColor': '(vec4 color) { return color; }',
1936+
'void afterFragment': '() {}'
1937+
}
1938+
}
18611939
);
18621940
}
18631941

18641942
return this._defaultColorShader;
18651943
}
18661944

1945+
/**
1946+
* TODO(dave): un-private this when there is a way to actually override the
1947+
* shader used for points
1948+
*
1949+
* Get the shader used when drawing points with <a href="#/p5/point">`point()`</a>.
1950+
*
1951+
* You can call <a href="#/p5.Shader/modify">`pointShader().modify()`</a>
1952+
* and change any of the following hooks:
1953+
* - `void beforeVertex`: Called at the start of the vertex shader.
1954+
* - `vec3 getLocalPosition`: Update the position of vertices before transforms are applied. It takes in `vec3 position` and must return a modified version.
1955+
* - `vec3 getWorldPosition`: Update the position of vertices after transforms are applied. It takes in `vec3 position` and pust return a modified version.
1956+
* - `float getPointSize`: Update the size of the point. It takes in `float size` and must return a modified version.
1957+
* - `void afterVertex`: Called at the end of the vertex shader.
1958+
* - `void beforeFragment`: Called at the start of the fragment shader.
1959+
* - `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.
1960+
* - `vec4 getFinalColor`: Update the final color after mixing. It takes in a `vec4 color` and must return a modified version.
1961+
* - `void afterFragment`: Called at the end of the fragment shader.
1962+
*
1963+
* Call `pointShader().inspectHooks()` to see all the possible hooks and
1964+
* their default implementations.
1965+
*
1966+
* @returns {p5.Shader} The `point()` shader
1967+
* @private()
1968+
*/
1969+
pointShader() {
1970+
return this._getPointShader();
1971+
}
1972+
18671973
_getPointShader() {
18681974
if (!this._defaultPointShader) {
18691975
this._defaultPointShader = new p5.Shader(
18701976
this,
18711977
this._webGL2CompatibilityPrefix('vert', 'mediump') +
18721978
defaultShaders.pointVert,
18731979
this._webGL2CompatibilityPrefix('frag', 'mediump') +
1874-
defaultShaders.pointFrag
1980+
defaultShaders.pointFrag,
1981+
{
1982+
vertex: {
1983+
'void beforeVertex': '() {}',
1984+
'vec3 getLocalPosition': '(vec3 position) { return position; }',
1985+
'vec3 getWorldPosition': '(vec3 position) { return position; }',
1986+
'float getPointSize': '(float size) { return size; }',
1987+
'void afterVertex': '() {}'
1988+
},
1989+
fragment: {
1990+
'void beforeFragment': '() {}',
1991+
'vec4 getFinalColor': '(vec4 color) { return color; }',
1992+
'bool shouldDiscard': '(bool outside) { return outside; }',
1993+
'void afterFragment': '() {}'
1994+
}
1995+
}
18751996
);
18761997
}
18771998
return this._defaultPointShader;
18781999
}
18792000

2001+
strokeShader() {
2002+
return this._getLineShader();
2003+
}
2004+
18802005
_getLineShader() {
18812006
if (!this._defaultLineShader) {
18822007
this._defaultLineShader = new p5.Shader(
18832008
this,
18842009
this._webGL2CompatibilityPrefix('vert', 'mediump') +
18852010
defaultShaders.lineVert,
18862011
this._webGL2CompatibilityPrefix('frag', 'mediump') +
1887-
defaultShaders.lineFrag
2012+
defaultShaders.lineFrag,
2013+
{
2014+
vertex: {
2015+
'void beforeVertex': '() {}',
2016+
'vec3 getLocalPosition': '(vec3 position) { return position; }',
2017+
'vec3 getWorldPosition': '(vec3 position) { return position; }',
2018+
'float getStrokeWeight': '(float weight) { return weight; }',
2019+
'vec2 getLineCenter': '(vec2 center) { return center; }',
2020+
'vec2 getLinePosition': '(vec2 position) { return position; }',
2021+
'vec4 getVertexColor': '(vec4 color) { return color; }',
2022+
'void afterVertex': '() {}'
2023+
},
2024+
fragment: {
2025+
'void beforeFragment': '() {}',
2026+
'Inputs getPixelInputs': '(Inputs inputs) { return inputs; }',
2027+
'vec4 getFinalColor': '(vec4 color) { return color; }',
2028+
'bool shouldDiscard': '(bool outside) { return outside; }',
2029+
'void afterFragment': '() {}'
2030+
}
2031+
}
18882032
);
18892033
}
18902034

@@ -2102,7 +2246,7 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
21022246
fillShader.setUniform('uSpecular', this._useSpecularMaterial);
21032247
fillShader.setUniform('uEmissive', this._useEmissiveMaterial);
21042248
fillShader.setUniform('uShininess', this._useShininess);
2105-
fillShader.setUniform('metallic', this._useMetalness);
2249+
fillShader.setUniform('uMetallic', this._useMetalness);
21062250

21072251
this._setImageLightUniforms(fillShader);
21082252

@@ -2175,14 +2319,7 @@ p5.RendererGL = class RendererGL extends p5.Renderer {
21752319
let diffusedLight = this.getDiffusedTexture(this.activeImageLight);
21762320
shader.setUniform('environmentMapDiffused', diffusedLight);
21772321
let specularLight = this.getSpecularTexture(this.activeImageLight);
2178-
// In p5js the range of shininess is >= 1,
2179-
// Therefore roughness range will be ([0,1]*8)*20 or [0, 160]
2180-
// The factor of 8 is because currently the getSpecularTexture
2181-
// only calculated 8 different levels of roughness
2182-
// The factor of 20 is just to spread up this range so that,
2183-
// [1, max] of shininess is converted to [0,160] of roughness
2184-
let roughness = 20 / this._useShininess;
2185-
shader.setUniform('levelOfDetail', roughness * 8);
2322+
21862323
shader.setUniform('environmentMapSpecular', specularLight);
21872324
}
21882325
}

0 commit comments

Comments
 (0)