如何在THREE.js中为精灵应用自定义着色器
How to apply custom shader to sprite in THREE.js
我希望能够应用一些程序结构的面孔。当我面对这样的需求时,我的第一个任务是制作广告牌,上面画着在开放空间里的核爆炸。我希望把它做成一个动画的径向渐变,我已经部分成功了。
对于每个片段着色器来说,主要的事情是可以访问UV
作为统一的变量。
似乎渲染精灵的主要事情是在顶点着色器中访问相机投影矩阵。
这里有个例子http://goo.gl/A7pY01!
现在我想把它画到广告牌精灵上。我本应该用THREE.Sprite
和THREE.ShaderMaterial
来做这个,但是没有成功。看来,THREE.SpriteMaterial
只是精灵的好材料。在检查了一些源代码后,我揭示了为什么精灵是使用插件以一种特殊的方式绘制的。
所以,在我发现自己发明自己的自行车之前,我觉得有必要问别人如何在不使用THREE.js的情况下将自己的自定义着色器放置在自己的自定义精灵上。
所以。经过一些小的研究和工作,我认为THREE.ShaderMaterial
是完成这个小任务的最佳选择。多亏了/extras/renderers/plugins/SpritePlugin
,我意识到如何使用顶点着色器来形成和定位精灵。我还有一些问题,但我找到了一个很好的解决办法。
为了完成我的任务,首先我创建了一个简单的平面几何:
var geometry = new THREE.PlaneGeometry( 1, 1 );
并使用它与ShaderMaterial
:
uniforms = {
cur_time: {type:"f", value:1.0},
beg_time:{type:"f", value:1.0},
scale:{type: "v3", value:new THREE.Vector3()}
};
var material = new THREE.ShaderMaterial( {
uniforms: uniforms,
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
transparent: true,
blending:THREE.AdditiveBlending // It looks like real blast with Additive blending!!!
} );
var mesh = new THREE.Mesh( geometry, material );
下面是我的着色器:顶点着色器: varying vec2 vUv;
uniform vec3 scale;
void main() {
vUv = uv;
float rotation = 0.0;
vec3 alignedPosition = vec3(position.x * scale.x, position.y * scale.y, position.z*scale.z);
vec2 pos = alignedPosition.xy;
vec2 rotatedPosition;
rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;
rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;
vec4 finalPosition;
finalPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );
finalPosition.xy += rotatedPosition;
finalPosition = projectionMatrix * finalPosition;
gl_Position = finalPosition;
}
我从原始Sprite Plugin源代码中获得顶点着色器,并稍微改变了它。顺便说一句,将+=
更改为=
会使精灵具有屏幕粘性。这件事浪费了我很多时间。
uniform float cur_time;
uniform float beg_time;
varying vec2 vUv;
void main() {
float full_time = 5000.;
float time_left = cur_time - beg_time;
float expl_step0 = 0.;
float expl_step1 = 0.3;
float expl_max = 1.;
float as0 = 0.;
float as1 = 1.;
float as2 = 0.;
float time_perc = clamp( (time_left / full_time), 0., 1. ) ;
float alphap;
alphap = mix(as0,as1, smoothstep(expl_step0, expl_step1, time_perc));
alphap = mix(alphap,as2, smoothstep(expl_step1, expl_max, time_perc));
vec2 p = vUv;
vec2 c = vec2(0.5, 0.5);
float max_g = 1.;
float dist = length(p - c) * 2. ;
float step1 = 0.;
float step2 = 0.2;
float step3 = 0.3;
vec4 color;
float a0 = 1.;
float a1 = 1.;
float a2 = 0.7;
float a3 = 0.0;
vec4 c0 = vec4(1., 1., 1., a0 * alphap);
vec4 c1 = vec4(0.9, 0.9, 1., a1 * alphap);
vec4 c2 = vec4(0.7, 0.7, 1., a2 * alphap);
vec4 c3 = vec4(0., 0., 0., 0.);
color = mix(c0, c1, smoothstep(step1, step2, dist));
color = mix(color, c2, smoothstep(step2, step3, dist));
color = mix(color, c3, smoothstep(step3, max_g, dist));
gl_FragColor = color;
}
这是一个如何制作多点渐变的例子,按时间动画。有很多优化和一些想法如何使它更漂亮。
但是这个几乎是我想要的。
- 从HTTPGET返回一个自定义对象列表,以便在Angular 2应用程序中使用
- 自定义运行时Can'在谷歌应用引擎中看不到我的自定义日志
- 如何在angular.js中动态应用自定义过滤器
- 如何在ExtJs4应用程序上为视图、存储和模型设置自定义文件夹名称
- 制作自定义铬应用程序顶部栏
- 使用javascript为web应用程序自定义键盘快捷键
- 如何在Sencha Touch应用程序中实现自定义Toast
- 如何在 Rails 应用程序中向 Galleria 添加自定义描述
- 通过应用自定义 css 类禁用 html 输入元素
- 使用css类将自定义样式应用于上下文按钮的Highcharts
- $injector:modulerr将自定义模块注入Angular应用程序
- Rally自定义应用程序复选框筛选器不工作
- 如何在自定义应用程序中使用后退按钮访问Fiori启动板
- 创建 JavaScript 自定义应用程序的新实例
- 从网页打开自定义应用程序
- 自定义应用程序启动屏幕
- 自定义应用程序的动态高度
- 使用node.js一步一步创建自定义应用程序
- 有没有办法让窗口在窗口中包含自定义应用程序
- 由于日光节约已经开始,我的自定义应用程序不工作