shader 传 世界坐标的uniform 在web 和 模拟器没问题,android有坐标的偏移

shader的效果是 将本节点内的渲染保持原色,节点外的部分保持灰色。
这个是浏览器和模拟器的效果:

在android真机上跑就会出现偏移。点击位置和shader方块位置的映射关系是这样的(touchX,touchY)=>(worldPositionX/2,worldPositionY/2)

真机 不知道怎么截gif 放一张图吧。这是一运行的情况,立马出现偏移。默认的shader方块是在正中央的

这是shader的调用代码:

 gray-bound-box.js

let vert = require('gray-bound-box-vert');
let frag = require('gray-bound-box-frag');
let vertNative = require('gray-bound-box-native-vert');
cc.Class({
    extends: cc.Component,

    properties: {
        _left: 0.0,
        _right:0.0,
        _up:0.0,
        _down:0.0,
        grayTarget:cc.Node,

    },

    onLoad() {
        this.onBoundChanged();
        this.node.on('size-changed',this.onBoundChanged,this);
        this.node.on('position-changed',this.onBoundChanged,this);

        this.node.on('touchmove',e=>{this.node.position = this.node.parent.convertToNodeSpaceAR(e.getLocation())})
       
    },

    onBoundChanged(){
        this.updateBoundBox();
        this.render(this._left,this._right,this._up,this._down);
    },

    updateBoundBox(){
        let leftDownPoint = cc.pSub(this.node.position,cc.v2(this.node.width * this.node.anchorX,this.node.height * this.node.anchorY));
        let rightUpPoint = cc.pAdd(leftDownPoint,cc.v2(this.node.width,this.node.height));

        let leftDownWorldPoint = this.node.parent.convertToWorldSpaceAR(leftDownPoint);
        let rightUpWorldPoint = this.node.parent.convertToWorldSpaceAR(rightUpPoint);

        this._left = leftDownWorldPoint.x;
        this._down = leftDownWorldPoint.y;
        this._right = rightUpWorldPoint.x;
        this._up = rightUpWorldPoint.y;
    },

    render(left,right,up,down) {
        if (!this._program) {
            this._program = new cc.GLProgram();
        } if (cc.sys.isNative) {
            this._program.initWithString(vertNative,frag);
            this._program.link();
            this._program.updateUniforms();
            let glProgram_state = cc.GLProgramState.getOrCreateWithGLProgram(this._program);
            glProgram_state.setUniformFloat("left",left);
            glProgram_state.setUniformFloat("right",right);
            glProgram_state.setUniformFloat("up",up);
            glProgram_state.setUniformFloat("down",down);
        } else {
           this._program.initWithString(vert, frag);
            this._program.addAttribute(cc.macro.ATTRIBUTE_NAME_POSITION, cc.macro.VERTEX_ATTRIB_POSITION);
            this._program.addAttribute(cc.macro.ATTRIBUTE_NAME_COLOR, cc.macro.VERTEX_ATTRIB_COLOR);
            this._program.addAttribute(cc.macro.ATTRIBUTE_NAME_TEX_COORD, cc.macro.VERTEX_ATTRIB_TEX_COORDS);
            this._program.link();
            this._program.updateUniforms();
            this._program.setUniformLocationWith1f(this._program.getUniformLocationForName("left"), left);
            this._program.setUniformLocationWith1f(this._program.getUniformLocationForName("right"), right);
            this._program.setUniformLocationWith1f(this._program.getUniformLocationForName("up"), up);
            this._program.setUniformLocationWith1f(this._program.getUniformLocationForName("down"), down);
        }
        this.setProgram(this.grayTarget._sgNode,this._program);
    },

    setProgram(sgNode,program){
        if (cc.sys.isNative) {
            let glProgram_state = cc.GLProgramState.getOrCreateWithGLProgram(program);
            sgNode.setGLProgramState(glProgram_state);
        } else {
            sgNode.setShaderProgram(program);
        }

        let children = sgNode.children;

        for (let i = 0; i < children.length; i++) {
            this.setProgram(children[i], program);
        }   
    }
});

这是两份顶点着色器:

   gray-bound-box-vert.js

   module.exports = 
   
   attribute vec4 a_position;
   attribute vec2 a_texCoord;
   attribute vec4 a_color; 
   varying vec2 v_texCoord;
   varying vec4 v_fragmentColor;
   void main() 
   {
       gl_Position = CC_PMatrix * a_position;
       v_fragmentColor = a_color;
       v_texCoord = a_texCoord;
   }

   gray-bound-box-native-vert.js

   module.exports = 
   
   attribute vec4 a_position;
   attribute vec2 a_texCoord;
   attribute vec4 a_color; 
   varying vec2 v_texCoord;
   varying vec4 v_fragmentColor;
   void main() 
   {
       gl_Position = CC_PMatrix * CC_MVMatrix * a_position;
       v_fragmentColor = a_color;
       v_texCoord = a_texCoord;
   }

这是片元着色器:


gray-bound-box-frag.js

module.exports = 

varying vec2 v_texCoord;
uniform float left;
uniform float right;
uniform float up;
uniform float down;

void main() {
    vec4 texColor = texture2D(CC_Texture0, v_texCoord).rgba;
    if(gl_FragCoord.x > left && gl_FragCoord.x < right && gl_FragCoord.y < up && gl_FragCoord.y > down) {
        gl_FragColor = texColor; 
    }else {
        float avg = (texColor.r + texColor.g + texColor.b) / 3.0;
        gl_FragColor = vec4(avg,avg,avg,texColor.a);       
    }
}


这就很尴尬了,是不是和子龙大大那个截图后出现在左下角有异曲同工之妙?
可我去翻了textureRender.cpp 在1.5b2已经改过来了。

1赞

在web重现android 偏移的方法

在 gray-bound-box.js的updateBoundBox中 将left right up down 四条边的坐标转换到Canvas节点下。

   updateBoundBox(){
        let leftDownPoint = cc.pSub(this.node.position,cc.v2(this.node.width * this.node.anchorX,this.node.height * 
   this.node.anchorY));
        let rightUpPoint = cc.pAdd(leftDownPoint,cc.v2(this.node.width,this.node.height));
        let leftDownWorldPoint = cc.find('Canvas').convertToNodeSpaceAR(this.node.parent.convertToWorldSpaceAR(leftDownPoint));
        let rightUpWorldPoint = cc.find('Canvas').convertToNodeSpaceAR(this.node.parent.convertToWorldSpaceAR(rightUpPoint));
        this._left = leftDownWorldPoint.x;
        this._down = leftDownWorldPoint.y;
        this._right = rightUpWorldPoint.x;
        this._up = rightUpWorldPoint.y;
    },

楼主解决了吗.最近我也遇到这个问题了,比如shader绘制的精灵放在另一个缩放大小并且移动位置的精灵里,就会出现稍微错位的问题.