glsl - WebGL2:不同着色器中的相同功能
问题描述
我有一个包含复杂数学的大函数,我想在几个片段着色器中调用这个相同的函数。我是否必须将函数的代码复制粘贴到每个着色器?或者有什么办法可以避免这种情况,在着色器之间共享代码?我可以为常用着色器功能提供任何类型的“库”吗?
解决方案
在 WebGL 的着色器中共享代码的方法是通过字符串操作。例子
const hsv2rgb = `
vec3 hsv2rgb(vec3 c) {
c = vec3(c.x, clamp(c.yz, 0.0, 1.0));
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
`;
const fragmentShader1 = `#version 300 es
${hsv2rgb}
in float hue;
out vec4 color;
void main() {
color = vec4(hsv2Rgb(vec3(hue, 1.0, 0.8)), 1);
}
const fragmentShader2 = `#version 300 es
${hsv2rgb}
in vec3 hsv;
out vec4 color;
void main() {
color = vec4(hsv2Rgb(hsv), 1);
}
`;
不需要图书馆,因为它很简单。例子
例子
const snippets = {
hsv2rgb: `...code-from-above--...`,
rgb2hsv: `...some code ...`,
};
现在只需使用片段
const fragmentShader2 = `#version 300 es
${snippets.hsv2rgb}
${snippets.rgb2hsv}
in vec3 v_color;
out vec4 color;
void main() {
vec3 hsv = rgb2hsv(v_color);
color = vec4(hsv2Rgb(hsv + vec3(0.5, 0, 0), 1);
}
`;
尽管我建议不要使用对象来收集字符串,因为您使用的任何构建器都可能无法丢弃未使用的片段。
组织你可以使用 es6 导入
/* hsv2rgb.glsl.js */
export default `
vec3 hsv2rgb(vec3 c) {
c = vec3(c.x, clamp(c.yz, 0.0, 1.0));
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
`;
然后你可以导入
/* somefragshader.glsl.js */
import hsv2rgb from './hsv2rgb.glsl.js';
export default `#version 300 es
${hsv2rgb}
in vec3 hsv;
out vec4 color;
void main() {
color = vec4(hsv2Rgb(hsv), 1);
}
`;
然后在一些程序中使用
import someFragmentShaderSource from './somefragmentshader.glsl.js';
...
...compile shader using someFragmentShaderSource ...
如果您不喜欢使用模板字符串替换,那么制作自己的字符串是微不足道的
const subs = {
hsv2rgb: `...code-from-above--...`,
rgb2hsv: `...some code ...`,
};
// replace `#include <name>` with named sub
function replaceSubs(str, subs) {
return str.replace(/#include\s+<(\w+)>/g, (m, key) => {
return subs[key];
});
}
接着
const fragmentShader2 = replaceSubs(`#version 300 es
#include <hsv2rgb>
in vec3 hsv;
out vec4 color;
void main() {
color = vec4(hsv2Rgb(hsv), 1);
}
`, snippets);
推荐阅读
- postgresql - Postgres & docker os 磁盘缓存
- git - Visual Studio 的 git 集成找不到我的文件的历史记录
- javascript - CSS:如何使 div 扩展到可滚动容器之外
- python - RuntimeError:堆栈期望每个张量与 fastaudio 模块大小相等
- java - 添加 MySQL/MariaDB 依赖会破坏 Maven/Jira-Plugin
- c# - 如何使活动指示器等待功能
- firebase - Nuxt SSR - Firebase 托管
- r - 需要帮助在 URL 列表上循环这些函数并将聚合数据组合到一个表中
- python - 将二维数组的二维数组转换为numpy中的二维数组
- django - 距离 Postgis Django Postgres