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

Make Cesium's shaders editable with the SpectorJS shader editor #8608

Merged
merged 5 commits into from
Mar 27, 2020
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
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Change Log

* Added basic underground rendering support. When the camera is underground the globe will be rendered as a solid surface and underground entities will not be culled. [#8572](https://github.com/AnalyticalGraphicsInc/cesium/pull/8572)
* The `CesiumUnminified` build now includes sourcemaps.
* Added the ability to edit CesiumJS shaders on-the-fly using the [SpectorJS](https://spector.babylonjs.com/) Shader Editor.

##### Fixes :wrench:

Expand Down
60 changes: 59 additions & 1 deletion Source/Renderer/ShaderProgram.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,18 @@ import createUniformArray from './createUniformArray.js';
* @private
*/
function ShaderProgram(options) {
var modifiedFS = handleUniformPrecisionMismatches(options.vertexShaderText, options.fragmentShaderText);
var vertexShaderText = options.vertexShaderText;
var fragmentShaderText = options.fragmentShaderText;

if (typeof spector !== 'undefined') {
// The #line statements common in Cesium shaders interfere with the ability of the
// SpectorJS to show errors on the correct line. So remove them when SpectorJS
// is active.
vertexShaderText = vertexShaderText.replace(/^#line/mg, '//#line');
fragmentShaderText = fragmentShaderText.replace(/^#line/mg, '//#line');
}

var modifiedFS = handleUniformPrecisionMismatches(vertexShaderText, fragmentShaderText);

this._gl = options.gl;
this._logShaderCompilation = options.logShaderCompilation;
Expand Down Expand Up @@ -432,6 +443,12 @@ import createUniformArray from './createUniformArray.js';
return;
}

reinitialize(shader);
}

function reinitialize(shader) {
var oldProgram = shader._program;

var gl = shader._gl;
var program = createAndLinkProgram(gl, shader, shader._debugShaders);
var numberOfVertexAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
Expand All @@ -447,6 +464,47 @@ import createUniformArray from './createUniformArray.js';
shader._manualUniforms = partitionedUniforms.manualUniforms;

shader.maximumTextureUnitIndex = setSamplerUniforms(gl, program, uniforms.samplerUniforms);

if (oldProgram) {
shader._gl.deleteProgram(oldProgram);
}

// If SpectorJS is active, add the hook to make the shader editor work.
// https://github.com/BabylonJS/Spector.js/blob/master/documentation/extension.md#shader-editor
if (typeof spector !== 'undefined') {
shader._program.__SPECTOR_rebuildProgram = function(
vertexSourceCode, // The new vertex shader source
fragmentSourceCode, // The new fragment shader source
onCompiled, // Callback triggered by your engine when the compilation is successful. It needs to send back the new linked program.
onError // Callback triggered by your engine in case of error. It needs to send the WebGL error to allow the editor to display the error in the gutter.
) {
var originalVS = shader._vertexShaderText;
var originalFS = shader._fragmentShaderText;

// SpectorJS likes to replace `!=` with `! =` for unknown reasons,
// and that causes glsl compile failures. So fix that up.
var regex = / ! = /g;
shader._vertexShaderText = vertexSourceCode.replace(regex, ' != ');
shader._fragmentShaderText = fragmentSourceCode.replace(regex, ' != ');

try {
reinitialize(shader);
onCompiled(shader._program);
} catch (e) {
shader._vertexShaderText = originalVS;
shader._fragmentShaderText = originalFS;

// Only pass on the WebGL error:
var errorMatcher = /(?:Compile|Link) error: ([^]*)/;
var match = errorMatcher.exec(e.message);
if (match) {
onError(match[1]);
} else {
onError(e.message);
}
}
};
}
}

ShaderProgram.prototype._bind = function() {
Expand Down