Skip to content

Commit

Permalink
Merge 04ac7fc into 525d8b2
Browse files Browse the repository at this point in the history
  • Loading branch information
Pessimistress committed Jul 21, 2019
2 parents 525d8b2 + 04ac7fc commit 45f2939
Show file tree
Hide file tree
Showing 15 changed files with 282 additions and 345 deletions.
30 changes: 30 additions & 0 deletions docs/developer-guide/shadertools/writing-shader-modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Descriptor objects can define the following fields:
* `vs` - (String | null)
* `fs` - (String | null)
* `getUniforms` JavaScript function that maps JavaScript parameter keys to uniforms used by this module
* `uniforms` (*Object*) - a light alternative to `getUniforms`, see below
* `dependencies` (*Array*) - a list of other shader modules that this module is dependent on
* `deprecations` (*Array*) - a list of deprecated APIs.

Expand Down Expand Up @@ -79,6 +80,35 @@ The function should return a JavaScript object with keys representing uniform na
The function should expect the shape of the dependency uniforms to vary based on what's passed in `opts`. This behavior is intended because we only want to recalculate a uniform if the uniforms that it depends on are changed. An example is the `project` and `project64` modules in deck.gl. When `opts.viewport` is provided, `project64` will receive the updated projection matrix generated by the `project` module. If `opts.viewport` is empty, then the `project` module generates nothing and so should `project64`.


### uniforms

If the uniforms of this module can be directly pulled from user settings, they may declaratively defined by a `uniforms` object:

```js
{
name: 'my-shader-module',
uniforms: {
strength: {type: 'number', value: 1, min: 0, max: 1},
center: [0.5, 0.5]
}
}
```

At runtime, this map will be used to generate the uniforms needed by the shaders. If either `strength` or `center` is present in the user's module settings, then the user's value will be used; otherwise, the default value in the original definition will be used.

Each uniform definition may contain the following fields:

* `type` (*String*) - one of `number`, `boolean`, `array` or `object`
* `value` - the default value of this uniform

With `type: 'number'`, the following additional fields may be added for validation:

* `min` (*Number*)
* `max` (*Number*)

Note: `uniforms` is ignored if `getUniforms` is provided.


### Platform Detection

Also does platform detection and injects `#define` statements enabling your shader to conditionally use code.
4 changes: 2 additions & 2 deletions modules/shadertools/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export {assembleShaders, createShaderHook, createModuleInjection} from './lib/as

// HELPERS
export {combineInjects} from './lib/inject-shader';
export {normalizeShaderModule} from './lib/filters/normalize-module';
export {normalizeShaderModule} from './lib/shader-module';

// UTILS
export {
Expand All @@ -33,5 +33,5 @@ export * from './modules';
export const MODULAR_SHADERS = {
vs: MODULAR_VS,
fs: MODULAR_FS,
defaultUniforms: {}
uniforms: {}
};
8 changes: 5 additions & 3 deletions modules/shadertools/src/lib/assemble-shaders.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export function createModuleInjection(moduleName, opts) {
}

// Inject a list of modules
export function assembleShaders(gl, opts = {}) {
export function assembleShaders(gl, opts) {
const {vs, fs} = opts;
const modules = resolveModules(opts.modules || []);
return {
Expand All @@ -65,7 +65,7 @@ export function assembleShaders(gl, opts = {}) {
// adding prologues, requested module chunks, and any final injections.
function assembleShader(
gl,
{id, source, type, modules = [], defines = {}, inject = {}, prologue = true, log}
{id, source, type, modules, defines = {}, inject = {}, prologue = true, log}
) {
assert(typeof source === 'string', 'shader source must be a string');

Expand Down Expand Up @@ -133,7 +133,9 @@ ${isVertex ? '' : FRAGMENT_SHADER_PROLOGUE}
break;

default:
module.checkDeprecations(coreSource, log);
if (log) {
module.checkDeprecations(coreSource, log);
}
const moduleSource = module.getModuleSource(type, glslVersion);
// Add the module source, and a #define that declares it presence
assembledSource += moduleSource;
Expand Down
41 changes: 0 additions & 41 deletions modules/shadertools/src/lib/filters/normalize-module.js

This file was deleted.

105 changes: 22 additions & 83 deletions modules/shadertools/src/lib/filters/prop-types.js
Original file line number Diff line number Diff line change
@@ -1,117 +1,56 @@
// // import assert from '../../utils'; // TODO

const TYPE_DEFINITIONS = {
boolean: {
validate(value, propType) {
return true;
}
},
number: {
validateType(value, propType) {
return (
'value' in propType &&
(!('max' in propType) || Number.isFinite(propType.max)) &&
(!('min' in propType) || Number.isFinite(propType.min))
);
},
validate(value, propType) {
return (
Number.isFinite(value) &&
(!('max' in propType) || value <= propType.max) &&
(!('min' in propType) || value >= propType.min)
);
}
},
array: {
validate(value, propType) {
return Array.isArray(value) || ArrayBuffer.isView(value);
}
}
};

export function parsePropTypes(propDefs) {
const propTypes = {};
const defaultProps = {};
for (const [propName, propDef] of Object.entries(propDefs)) {
const propType = parsePropType(propName, propDef);
for (const propName in propDefs) {
const propDef = propDefs[propName];
const propType = parsePropType(propDef);
propTypes[propName] = propType;
defaultProps[propName] = propType.value;
}
return {propTypes, defaultProps};
return propTypes;
}

// Parses one property definition entry. Either contains:
// * a valid prop type object ({type, ...})
// * or just a default value, in which case type and name inference is used
function parsePropType(name, propDef) {
switch (getTypeOf(propDef)) {
case 'object':
propDef = normalizePropType(name, propDef);
return parsePropDefinition(propDef);

case 'array':
return guessArrayType(name, propDef);

case 'boolean':
return {name, type: 'boolean', value: propDef};

case 'number':
return guessNumberType(name, propDef);

case 'function':
return {name, type: 'function', value: propDef};
// return guessFunctionType(name, propDef);

default:
return {name, type: 'unknown', value: propDef};
}
}

function guessArrayType(name, array) {
if (/color/i.test(name) && (array.length === 3 || array.length === 4)) {
return {name, type: 'color', value: array};
}
return {name, type: 'array', value: array};
}

function normalizePropType(name, propDef) {
if (!('type' in propDef)) {
function parsePropType(propDef) {
let type = getTypeOf(propDef);
if (type === 'object') {
if (!propDef) {
return {type: 'object', value: null};
}
if ('type' in propDef) {
return Object.assign({}, propDef, TYPE_DEFINITIONS[propDef.type]);
}
if (!('value' in propDef)) {
// If no type and value this object is likely the value
return {name, type: 'object', value: propDef};
return {type: 'object', value: propDef};
}
return Object.assign({name, type: getTypeOf(propDef.value)}, propDef);
type = getTypeOf(propDef.value);
return Object.assign({type}, propDef, TYPE_DEFINITIONS[type]);
}
return Object.assign({name}, propDef);
}

function parsePropDefinition(propDef) {
const {type} = propDef;
const typeDefinition = TYPE_DEFINITIONS[type] || {};
const {typeValidator} = typeDefinition;
if (typeValidator) {
// assert(typeValidator(propDef), 'Illegal prop type');
}

return propDef;
}

function guessNumberType(name, value) {
const isKnownProp =
/radius|scale|width|height|pixel|size|miter/i.test(name) && /^((?!scale).)*$/.test(name);
const max = isKnownProp ? 100 : 1;
const min = 0;
return {
name,
type: 'number',
max: Math.max(value, max),
min: Math.min(value, min),
value
};
return Object.assign({type, value: propDef}, TYPE_DEFINITIONS[type]);
}

// improved version of javascript typeof that can distinguish arrays and null values
function getTypeOf(value) {
if (Array.isArray(value) || ArrayBuffer.isView(value)) {
return 'array';
}
if (value === null) {
return 'null';
}
return typeof value;
}
39 changes: 0 additions & 39 deletions modules/shadertools/src/lib/filters/shader-pass.js

This file was deleted.

2 changes: 1 addition & 1 deletion modules/shadertools/src/lib/inject-shader.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export default function injectShader(source, type, inject, injectStandardStubs)

// Finally, if requested, insert an automatic module injector chunk
if (injectStandardStubs) {
source = source.replace('}s*$', match => match + MODULE_INJECTORS[type]);
source = source.replace(/\}\s*$/, match => match + MODULE_INJECTORS[type]);
}

return source;
Expand Down
Loading

0 comments on commit 45f2939

Please sign in to comment.