Quantcast
Channel: Cocos中文社区 - 最新主题
Viewing all articles
Browse latest Browse all 88737

Creator jsb下的shader真的是坨屎。

$
0
0

@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

阅读整个主题


Viewing all articles
Browse latest Browse all 88737

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>