@yangzhu626 写道:
一堆的api 没几个能用的。
我是要做战争迷雾,不想用拼接图块的方式做。准备用shader做。
web上实现了。效果如下
然后测jsb的时候我蒙逼了。
我这个实现是向shader传递一组坐标做为光照点和光照半径,
数据类似这样
var params = [
[100,0,100],
[200,0,100],
[300,0,100],
[400,0,100],
[500,0,100],
[600,0,100],
[700,0,100],
[800,0,100],
[900,0,100],
[480,320,100]
];
照亮的区域在shader中改变mask层的透明度。
然后发现传setUniformFloatv浮点数组传不过去,跟踪了下发现
说是浮点数组不支持。 不支持你把接口放这干嘛咯。
浮点数组不支持那我把半径改成用vec2 (cc.p())传行了吧。大不了一个值为雾。
用setUniformVec2v 结果发现更神奇的问题。
每次重启模拟器会发现迷雾的样子都不一样。我明明传递的是测试的一组数据。
最后我通过在shader中设定常数判断 vec2数组在向shader传递的时候出现了不知道原因的异常。每次c++向shader中传的数据都不一样。只有很偶尔会是正常的。这个问题我就搞不懂原因了。我又想换成vec3v一次把光源点和半径数组发到shader试试。发现jsb上 js里根本不知道怎么去构造vec3.
最后我想我只有去shader定义10个uniform 把数据分成10次传给shader.
想想就觉得这方案不靠谱。js调用c++本身性能就不咋滴。搜索了引擎的整个代码,发现官方根本就没有用到setUniformVec2v setUniformVec3v setUniformFloatv 只要是传数组的官方就没用过。
同时我发现js引擎下的shader支持还真的是很OK。不管传什么都可以轻松实现。就是jsb这坑
/**
* 战争迷雾管理器
* @param {[type]} ) { } [description]
* @param {[type]} } [description]
* @return {[type]} [description]
*/
cc.Class({
name:"UIWarFogMaskMediator",
extends: cc.Component,
properties: {}, onLoad: function () { }, start:function(){ var self = this; // setTimeout(function(){ cc.loader.loadResAll("Shaders", function(err, rep){ cc.log("------------", err); self.showWarFog(); }); // }, 5000) }, createShader:function(){ this.shader = new cc.GLProgram(); if(cc.sys.isNative){ var vs = cc.loader.getRes("Shaders/warFogVSH.vsh"), fs = cc.loader.getRes("Shaders/warFogFSH.fsh"); this.shader.initWithString(vs, fs); this.shader.link(); this.shader.updateUniforms(); // this.setProgram(this.maskSprite.node._sgNode, this.shader); } else { var vs = cc.loader.getRes("Shaders/warFogVSH.vsh"), fs = cc.loader.getRes("Shaders/warFogFSH.fsh"); this.shader.initWithVertexShaderByteArray(vs, fs); this.shader.addAttribute(cc.macro.ATTRIBUTE_NAME_POSITION, cc.macro.VERTEX_ATTRIB_POSITION); this.shader.addAttribute(cc.macro.ATTRIBUTE_NAME_COLOR, cc.macro.VERTEX_ATTRIB_COLOR); this.shader.addAttribute(cc.macro.ATTRIBUTE_NAME_TEX_COORD, cc.macro.VERTEX_ATTRIB_TEX_COORDS); this.shader.link(); this.shader.updateUniforms(); // this.spriteA.node._sgNode.setShaderProgram(this.shader); this.shader.use(); } }, setUniformLocation:function(lights){ var points = [], mradius = []; if(cc.sys.isNative){ for (var i in lights) { // points.push(cc.p(lights[i][0], lights[i][1])); points.push(cc.p(lights[i][0], lights[i][1])); mradius.push(cc.p(lights[i][2], 0)); } var glProgram_state = cc.GLProgramState.getOrCreateWithGLProgram(this.shader); // glProgram_state.setUniformFloatv("u_threshold", 1.75); glProgram_state.setUniformVec2v("lightPoints", 10, points); glProgram_state.setUniformVec2v("lightRadius", 10, mradius); } else { for (var i in lights) { // points.push(cc.p(lights[i][0], lights[i][1])); points.push(lights[i][0]); points.push(lights[i][1]); mradius.push(lights[i][2]); mradius.push(0); } this.shader.setUniformLocationWith2fv(this.shader.getUniformLocationForName('lightPoints'), points); this.shader.setUniformLocationWith2fv(this.shader.getUniformLocationForName('lightRadius'), mradius); } }, showWarFog:function(params){ cc.log("--------------------------------showWarFog") this.createShader(); var params = [ [100,0,100], [200,0,100], [300,0,100], [400,0,100], [500,0,100], [600,0,100], [700,0,100], [800,0,100], [0,0,100], // [100,100,100], // [200,200,100], // [300,300,100], [480,320,100] ]; this.setUniformLocation(params); this.setProgram(this.node._sgNode, this.shader); }, setProgram:function(node, program) { if (cc.sys.isNative) { var glProgram_state = cc.GLProgramState.getOrCreateWithGLProgram(program); node.setGLProgramState(glProgram_state); } else { node.setShaderProgram(program); } var children = node.children; if (!children) return; for (var i = 0; i < children.length; i++) { this.setProgram(children[i], program); } },
});
warFogFSH.fsh
varying vec4 v_fragmentColor;// vertex shader传入setColor设置的颜色
varying vec2 v_texCoord;// 纹理坐标
varying vec2 v_position;uniform vec2 lightPoint;// 迷雾的开放点
uniform vec2 lightPoints[10];// 迷雾的开放点
uniform vec2 lightRadius[10];// 灯塔的开放半径float getPointAlpha(vec2 cur_position)
{
float intensity = 0.0;//光照强度
for(int i = 0; i < 10; i++){
vec2 p = lightPoints[i];
float radius = lightRadius[i].x;//光源半径半径内光照强度为1
float d = distance(cur_position, p);//当前顶点与灯的距离
float _intensity = (2.0 * radius - d) / radius;
intensity = clamp(intensity, 0.0, 1.0);
intensity += _intensity;
}
intensity = clamp(intensity, 0.0, 1.0);
return 1.0 - intensity;
}
void main()
{
vec4 myC = texture2D(CC_Texture0, vec2(v_texCoord.x, v_texCoord.y));//正在处理的这个像素点的颜色
float alpha = getPointAlpha(v_position);
//if (alpha > 0.2) alpha = 0.2;
alpha *= 0.9;
myC.a = alpha;
gl_FragColor = v_fragmentColor * myC;
}warFogVSH.vsh
attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
varying vec2 v_position;void main()
{
gl_Position = CC_PMatrix * a_position;
v_fragmentColor = a_color;
v_position = a_position.xy;
v_texCoord = a_texCoord;
}使用方法 给一个全黑的精灵 绑定UIWarFogMaskMediator这个脚本就可以了。
模拟器上 启动10次可能有一次是正常的。
帖子: 2
参与者: 1