THREE.WebGLShader: 着色器无法编译; 's_noise_1_2' : 未找到匹配的重载函数
THREE.WebGLShader: Shader Couldn't Compile; 's_noise_1_2' : no matching overloaded function found
我一直在研究一些 THREE.js 示例,并一直在尝试编译示例中包含的一些着色器,具体而言:https://github.com/brunoimbrizi/interactive-particles
如果您导航至 src/shaders/,您将找到我正在尝试编译的着色器。我目前正在 运行 开发一个 React 应用程序,并且一直在更新此代码以满足我的个人项目需求,但我 运行 一路上遇到了这些问题:
No matching overloaded function found
THREE.WebGLRenderer 98
THREE.WebGLShader: Shader couldn't compile.
THREE.WebGLShader: gl.getShaderInfoLog() vertex WARNING: 0:1: 'glslify' : unrecognized pragma
ERROR: 0:40: 'snoise_1_2' : no matching overloaded function found
ERROR: 0:49: 'snoise_1_2' : no matching overloaded function found
我已经尝试以多种不同的方式重构 vertex/fragment 着色器代码,但不管我尝试的解决方案如何,结果都是一样的。似乎在 React 中对这样的东西的支持非常少,虽然 gl-react 似乎几乎有用,但我不需要组件形式的着色器。
particleFrag.js
const glsl = require('glslify');
export const fragShader = glsl`precision highp float;
uniform sampler2D uTexture;
varying vec2 vPUv;
varying vec2 vUv;
void main() {
vec4 color = vec4(0.0);
vec2 uv = vUv;
vec2 puv = vPUv;
vec4 colA = texture2D(uTexture, puv);
float grey = colA.r * 0.21 + colA.g * 0.71 + colA.b * 0.07;
vec4 colB = vec4(grey, grey, grey, 1.0);
float border = 0.3;
float radius = 0.5;
float dist = radius - distance(uv, vec2(0.5));
float t = smoothstep(0.0, border, dist);
color = colB;
color.a = t;
gl_FragColor = color;
}`;
particleVert.js
const glsl = require('glslify');
export const vertShader = glsl`#pragma glslify: snoise2 = require(glsl-noise/simplex/2d)
precision highp float;
attribute float pindex;
attribute vec3 position;
attribute vec3 offset;
attribute vec2 uv;
attribute float angle;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform float uTime;
uniform float uRandom;
uniform float uDepth;
uniform float uSize;
uniform vec2 uTextureSize;
uniform sampler2D uTexture;
uniform sampler2D uTouch;
varying vec2 vPUv;
varying vec2 vUv;
float random(float n) {
return fract(sin(n) * 43758.5453123);
}
void main() {
vUv = uv;
vec2 puv = offset.xy / uTextureSize;
vPUv = puv;
vec4 colA = texture2D(uTexture, puv);
float grey = colA.r * 0.21 + colA.g * 0.71 + colA.b * 0.07;
vec3 displaced = offset;
displaced.xy += vec2(random(pindex) - 0.5, random(offset.x + pindex) - 0.5) * uRandom;
float rndz = (random(pindex) + snoise_1_2(vec2(pindex * 0.1, uTime * 0.1)));
displaced.z += rndz * (random(pindex) * 2.0 * uDepth);
displaced.xy -= uTextureSize * 0.5;
float t = texture2D(uTouch, puv).r;
displaced.z += t * 20.0 * rndz;
displaced.x += cos(angle) * t * 20.0 * rndz;
displaced.y += sin(angle) * t * 20.0 * rndz;
float psize = (snoise_1_2(vec2(uTime, pindex) * 0.5) + 2.0);
psize *= max(grey, 0.2);
psize *= uSize;
vec4 mvPosition = modelViewMatrix * vec4(displaced, 1.0);
mvPosition.xyz += position * psize;
vec4 finalPosition = projectionMatrix * mvPosition;
gl_Position = finalPosition;
}`;
正在定义 material:
const material = new THREE.RawShaderMaterial({
uniforms,
vertexShader: shaders.particle.vert,
fragmentShader: shaders.particle.frag,
depthTest: false,
transparent: true,
// blending: THREE.AdditiveBlending
});
一切都源于这个渲染调用:
draw() {
this.renderer.render(this.scene, this.camera);
}
我显然需要着色器编译,我对这类事情的经验不足使得它很难在 React 项目中实现。
我通过执行以下操作设法解决了这个问题:
- 为我的项目添加了对 Babel/Webpack 的支持。
- 在 "container" 中渲染了由 CSS class 定义的粒子图像。
- 已验证 webpack 对 glslify 的支持。
在 React 项目中进行了很多更改以使其可操作,但使用 Babel 和 Webpack 进行转译似乎可以解决问题,因为 Webpack 支持着色器文件。
如果您对我如何更具体地获得此操作有任何疑问,请随时给我发消息!
webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const isDevelopment = process.env.NODE_ENV === 'development';
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader"
}
]
},
{
test: /\.(glsl|frag|vert)$/,
use: [
require.resolve('raw-loader'),
require.resolve('glslify-loader'),
]
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.module\.s([ac])ss$/,
loader: [
isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: true,
sourceMap: isDevelopment
}
},
{
loader: 'sass-loader',
options: {
sourceMap: isDevelopment
}
}
]
},
{
test: /\.s([ac])ss$/,
exclude: /\.module.(s(a|c)ss)$/,
loader: [
isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'sass-loader',
options: {
sourceMap: isDevelopment
}
}
]
},
{
test: /\.(jpe?g|gif|png|svg)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 10000
}
}
]
}
]
},
resolve: {
extensions: ['.js', '.jsx', '.scss', '.css', '.html', '.json', '.png']
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
}),
new MiniCssExtractPlugin({
filename: isDevelopment ? '[name].css' : '[name].[hash].css',
chunkFilename: isDevelopment ? '[id].css' : '[id].[hash].css'
})
]
};
我一直在研究一些 THREE.js 示例,并一直在尝试编译示例中包含的一些着色器,具体而言:https://github.com/brunoimbrizi/interactive-particles
如果您导航至 src/shaders/,您将找到我正在尝试编译的着色器。我目前正在 运行 开发一个 React 应用程序,并且一直在更新此代码以满足我的个人项目需求,但我 运行 一路上遇到了这些问题:
No matching overloaded function found
THREE.WebGLRenderer 98
THREE.WebGLShader: Shader couldn't compile.
THREE.WebGLShader: gl.getShaderInfoLog() vertex WARNING: 0:1: 'glslify' : unrecognized pragma
ERROR: 0:40: 'snoise_1_2' : no matching overloaded function found
ERROR: 0:49: 'snoise_1_2' : no matching overloaded function found
我已经尝试以多种不同的方式重构 vertex/fragment 着色器代码,但不管我尝试的解决方案如何,结果都是一样的。似乎在 React 中对这样的东西的支持非常少,虽然 gl-react 似乎几乎有用,但我不需要组件形式的着色器。
particleFrag.js
const glsl = require('glslify');
export const fragShader = glsl`precision highp float;
uniform sampler2D uTexture;
varying vec2 vPUv;
varying vec2 vUv;
void main() {
vec4 color = vec4(0.0);
vec2 uv = vUv;
vec2 puv = vPUv;
vec4 colA = texture2D(uTexture, puv);
float grey = colA.r * 0.21 + colA.g * 0.71 + colA.b * 0.07;
vec4 colB = vec4(grey, grey, grey, 1.0);
float border = 0.3;
float radius = 0.5;
float dist = radius - distance(uv, vec2(0.5));
float t = smoothstep(0.0, border, dist);
color = colB;
color.a = t;
gl_FragColor = color;
}`;
particleVert.js
const glsl = require('glslify');
export const vertShader = glsl`#pragma glslify: snoise2 = require(glsl-noise/simplex/2d)
precision highp float;
attribute float pindex;
attribute vec3 position;
attribute vec3 offset;
attribute vec2 uv;
attribute float angle;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform float uTime;
uniform float uRandom;
uniform float uDepth;
uniform float uSize;
uniform vec2 uTextureSize;
uniform sampler2D uTexture;
uniform sampler2D uTouch;
varying vec2 vPUv;
varying vec2 vUv;
float random(float n) {
return fract(sin(n) * 43758.5453123);
}
void main() {
vUv = uv;
vec2 puv = offset.xy / uTextureSize;
vPUv = puv;
vec4 colA = texture2D(uTexture, puv);
float grey = colA.r * 0.21 + colA.g * 0.71 + colA.b * 0.07;
vec3 displaced = offset;
displaced.xy += vec2(random(pindex) - 0.5, random(offset.x + pindex) - 0.5) * uRandom;
float rndz = (random(pindex) + snoise_1_2(vec2(pindex * 0.1, uTime * 0.1)));
displaced.z += rndz * (random(pindex) * 2.0 * uDepth);
displaced.xy -= uTextureSize * 0.5;
float t = texture2D(uTouch, puv).r;
displaced.z += t * 20.0 * rndz;
displaced.x += cos(angle) * t * 20.0 * rndz;
displaced.y += sin(angle) * t * 20.0 * rndz;
float psize = (snoise_1_2(vec2(uTime, pindex) * 0.5) + 2.0);
psize *= max(grey, 0.2);
psize *= uSize;
vec4 mvPosition = modelViewMatrix * vec4(displaced, 1.0);
mvPosition.xyz += position * psize;
vec4 finalPosition = projectionMatrix * mvPosition;
gl_Position = finalPosition;
}`;
正在定义 material:
const material = new THREE.RawShaderMaterial({
uniforms,
vertexShader: shaders.particle.vert,
fragmentShader: shaders.particle.frag,
depthTest: false,
transparent: true,
// blending: THREE.AdditiveBlending
});
一切都源于这个渲染调用:
draw() {
this.renderer.render(this.scene, this.camera);
}
我显然需要着色器编译,我对这类事情的经验不足使得它很难在 React 项目中实现。
我通过执行以下操作设法解决了这个问题:
- 为我的项目添加了对 Babel/Webpack 的支持。
- 在 "container" 中渲染了由 CSS class 定义的粒子图像。
- 已验证 webpack 对 glslify 的支持。
在 React 项目中进行了很多更改以使其可操作,但使用 Babel 和 Webpack 进行转译似乎可以解决问题,因为 Webpack 支持着色器文件。
如果您对我如何更具体地获得此操作有任何疑问,请随时给我发消息!
webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const isDevelopment = process.env.NODE_ENV === 'development';
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader"
}
]
},
{
test: /\.(glsl|frag|vert)$/,
use: [
require.resolve('raw-loader'),
require.resolve('glslify-loader'),
]
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.module\.s([ac])ss$/,
loader: [
isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: true,
sourceMap: isDevelopment
}
},
{
loader: 'sass-loader',
options: {
sourceMap: isDevelopment
}
}
]
},
{
test: /\.s([ac])ss$/,
exclude: /\.module.(s(a|c)ss)$/,
loader: [
isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'sass-loader',
options: {
sourceMap: isDevelopment
}
}
]
},
{
test: /\.(jpe?g|gif|png|svg)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 10000
}
}
]
}
]
},
resolve: {
extensions: ['.js', '.jsx', '.scss', '.css', '.html', '.json', '.png']
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
}),
new MiniCssExtractPlugin({
filename: isDevelopment ? '[name].css' : '[name].[hash].css',
chunkFilename: isDevelopment ? '[id].css' : '[id].[hash].css'
})
]
};