patuwwy/ShaderToy-Chrome-Plugin

Custom parameters for ShaderToys and custom textures

Closed this issue · 4 comments

For some reason Shader Toys hasn't been updated for some time and is lacking a lot of features.
I made a snippet code that reads parameters defined in Common tab and expands Shader Toys capabilities based on them.
So far I was only in need of custom images, so that is the first thing I implemented. Now its possible to add images from URL and also base64 encoded images.

Check this shader and also it's Common tab.

And run this code:

function getParameters() {
	// get id of common tab
	const commonTabImg = document.querySelector("img[src='/img/common.png']");
	if (!commonTabImg) return {};
	const commonTabId = Number.parseInt(commonTabImg.parentNode.id[3]);

	// get content of common tab
	const content = window.gShaderToy.mPass[commonTabId].mDocs.getValue();

	// get parameters from content
	const match = content.match(
		/\/\*[\s]*shadertoy-plugin parameters[\s\S]*?\*\//,
	); // Match the parameters comment block

	if (!match) return {};

	const parametersString = match[0]
		.replace(/\/\*\s*shadertoy-plugin parameters\s*/, "") // Remove the comment marker at start and "shadertoy-plugin parameters" line
		.replace(/\*\//, "") // Remove the closing comment marker
		.trim();

	try {
		return JSON.parse(parametersString); // Parse the parameters string as JSON
	} catch (error) {
		console.error("Error parsing shader parameters:", error);
		console.error(parametersString);
		return {};
	}
}

function evaluateParameters() {
	const params = getParameters();

	if (params.textures) {
		params.textures.forEach((texture, index) => {
			window.gShaderToy.mEffect.NewTexture(0, index, {
				mSrc: texture,
				mType: "texture",
				mID: 0,
				mSampler: {
					filter: "mipmap",
					wrap: "repeat",
					vflip: "true",
					srgb: "false",
					internal: "byte",
				},
			});
		});
	}
}

evaluateParameters();

In the mean time anyone interested in including own images in shaderToys can use this extension and let it run the above mentioned script.
Just add a comment anywhere inside Common tab that is in code block ( /* */ )
and on the second line has line " shadertoy-plugin parameters " and follows by json. Check this shader for more info.

I know it was mentioned before, but not implemented. #101

code i use inside the user-javascript extension:

function getParameters() {
	// get id of common tab
	const commonTabImg = document.querySelector("img[src='/img/common.png']");
	if (!commonTabImg) return {};
	const commonTabId = Number.parseInt(commonTabImg.parentNode.id[3]);

	// get content of common tab
	const content = window.gShaderToy.mPass[commonTabId].mDocs.getValue();

	// get parameters from content
	const match = content.match(
		/\/\*[\s]*shadertoy-plugin parameters[\s\S]*?\*\//
	); // Match the parameters comment block

	if (!match) return {};

	const parametersString = match[0]
		.replace(/\/\*\s*shadertoy-plugin parameters\s*/, '') // Remove the comment marker at start and "shadertoy-plugin parameters" line
		.replace(/\*\//, '') // Remove the closing comment marker
		.trim();

	try {
		return JSON.parse(parametersString); // Parse the parameters string as JSON
	} catch (error) {
		console.error('Error parsing shader parameters:', error);
		console.error(parametersString);
		return {};
	}
}

function evaluateParameters() {
	const params = getParameters();

	if (params.textures) {
		params.textures.forEach((texture, index) => {
			window.gShaderToy.mEffect.NewTexture(0, index, {
				mSrc: texture,
				mType: 'texture',
				mID: 0,
				mSampler: {
					filter: 'mipmap',
					wrap: 'repeat',
					vflip: 'true',
					srgb: 'false',
					internal: 'byte',
				},
			});
		});
	}
}

const originalSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function () {
	const xhr = this;
	xhr.addEventListener('load', function () {
		if (xhr.responseURL == 'https://www.shadertoy.com/shadertoy') {
			setTimeout(evaluateParameters, 300);
		}
	});
	return originalSend.apply(xhr, arguments);
};

window.addEventListener('load', function () {
	const compileButton = document.getElementById('compileButton');
	compileButton.addEventListener('click', function () {
		evaluateParameters();
	});
});

Do I understand correctly that you are cheating CORS in Response? Epic.

In this case no, I just needed a way to listen to when images where loaded because it sometimes happened that wrong preview was displayed in channels on site load even thought correct textures were applied inside shader
image_2024-05-12_030500529

kk, could you make a pull request?