creator 中使用自定义shader 显示错误

creator 版本: 1.42
如题,先上代码:
frag:
`
#ifdef GL_ES
precision mediump float;
#endif
uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;

void main( void ) {
// vec2 resolution = iResolution.xy;
// float time = iGlobalTime;
vec2 position = ((gl_FragCoord.xy / resolution.xy) * 2. - 1.) * vec2(resolution.x / resolution.y, 1.0);

float d = abs(0.3 + length(position) - 0.5 * abs(sin(time))) * 20.0;
vec3 cir = vec3(0.1/d, 0.1 / d, 0.2 / d);
vec3 bcol = vec3(1.0,0.8,0.7-0.07*position.y)*(1.0-0.25*length(position));  

float r = length(position);  
vec3 color = mix(bcol,cir,smoothstep(0.0,1.0,r));
gl_FragColor = vec4(color,1.0);
}

`

vert:
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; }

这是shadertoy测试的结果,是预期的结果:


但是在creator 加到精灵上之后如下如,一直显示在左下角,并没有被显示在精灵里面

这是creator中的精灵:


我还测试了一些在纹理上的特效,如模糊等,都是正常的,也就是传入的纹理坐标系是没问题的,但是单纯的用gl_FragCoord来计算做出来的动画就不是预期现实的效果。

我先请教各位怎么能让我画的东西在固定大小的精灵里面,这个是不是坐标矩阵转换有问题?望解答,感谢!
下面是js脚本:
var _default_vert = require("…/Shaders/ccShader_Default_Vert.js");
var _default_vert_no_mvp = require("…/Shaders/ccShader_Default_Vert_noMVP.js");

cc.Class({
extends: cc.Component,

properties: {
    glassFactor:1.0,
    flagShader:"",
    frag_glsl:{
        default:"Effect10.fs.glsl",
        visible:false,
    }
}, 

onLoad: function () {
    var self = this;
    this.parameters={
        startTime:Date.now(),
        time:0.0,
        mouse:{
            x:0.0,
            y:0.0,
        },
        resolution:{
            x:0.0,
            y:0.0,
        }

    };
    this.node.on(cc.Node.EventType.MOUSE_MOVE, function (event) {
        this.parameters.mouse.x = this.node.getContentSize().width / event.getLocationX();
        this.parameters.mouse.y = this.node.getContentSize().height / event.getLocationY(); 
    }, this);


    this.node.on( cc.Node.EventType.TOUCH_MOVE, function (event) {
        this.parameters.mouse.x = this.node.getContentSize().width / event.getLocationX();
        this.parameters.mouse.y = this.node.getContentSize().height / event.getLocationY(); 
    }, this);

    cc.loader.loadRes(self.flagShader,function(err,txt){
        if(err){
            cc.log(err)
        }else{
            self.frag_glsl = txt;
            self._use();
        }
    });

},
update:function(dt){
    if(this.glassFactor>=40){
        this.glassFactor=0;
    }
    this.glassFactor+=dt*3;

    if(this._program){

        this._program.use();
        this.updateGLParameters();
        if(cc.sys.isNative){
            var glProgram_state = cc.GLProgramState.getOrCreateWithGLProgram(this._program);
            glProgram_state.setUniformVec2( "resolution", this.parameters.resolution );
            glProgram_state.setUniformFloat( "time", this.parameters.time );    
            glProgram_state.setUniformVec2( "mouse" , this.parameters.mouse );
        }else{
            this._program.setUniformLocationWith2f( this._resolution, this.parameters.resolution.x,this.parameters.resolution.y );
            this._program.setUniformLocationWith1f( this._time, this.parameters.time );
            this._program.setUniformLocationWith2f( this._mouse, this.parameters.mouse.x,this.parameters.mouse.x );
        }
    }
},
updateGLParameters(){
    this.parameters.time = (Date.now() - this.parameters.startTime)/1000;
    this.parameters.resolution.x = ( this.node.getContentSize().width );
    this.parameters.resolution.y = ( this.node.getContentSize().height );


},

_use: function()
{
    
    if (cc.sys.isNative) {
        cc.log("use native GLProgram");
        this._program = new cc.GLProgram();
        this._program.initWithString(_default_vert_no_mvp, this.frag_glsl );


        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.updateGLParameters();


       
    }else{
        this._program = new cc.GLProgram();
        this._program.initWithVertexShaderByteArray(_default_vert_no_mvp, this.frag_glsl );
        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.use();

        this.updateGLParameters();

        this._program.setUniformLocationWith1f( this._program.getUniformLocationForName('time'), this.parameters.time );
        this._program.setUniformLocationWith2f( this._program.getUniformLocationForName('mouse'), this.parameters.mouse.x,this.parameters.mouse.y );
        this._program.setUniformLocationWith2f(this._program.getUniformLocationForName('resolution'), this.parameters.resolution.x,this.parameters.resolution.y );

    }

    

    
    if (cc.sys.isNative) {
        var glProgram_state = cc.GLProgramState.getOrCreateWithGLProgram(this._program);
        glProgram_state.setUniformVec2( "resolution", this.parameters.resolution );
        glProgram_state.setUniformFloat( "time" , this.parameters.time );
        glProgram_state.setUniformVec2( "mouse" , this.parameters.mouse );
    }else{


        this._resolution = this._program.getUniformLocationForName( "resolution" );
        this._time = this._program.getUniformLocationForName( "time" );
        this._mouse = this._program.getUniformLocationForName( "mouse" );

        this._program.setUniformLocationWith2f( this._resolution, this.parameters.resolution.x,this.parameters.resolution.y );
        this._program.setUniformLocationWith1f( this._time, this.parameters.time );
        this._program.setUniformLocationWith2f( this._mouse, this.parameters.mouse.x,this.parameters.mouse.y );
    }

    this.setProgram( this.node._sgNode ,this._program );
},

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);
}

});

1赞

我也遇到这个问题 现在还是不知道怎么解决。。

自己顶,之前用c++版本时,绘制前需要传入顶点参数,比如绘制纹理要传入4个顶点信息,来限制绘图区间,用这个js版好像默认是整个屏幕吧,我猜是这个原因,请问怎么传入这个精灵的顶点信息而不是用默认屏幕的

自顶一发

你的 resolution 的值有问题,gl_FragCoord 是像素在 Canvas 像素空间内的值,而 this.node.getContentSize() 获取的是设计分辨率下的节点尺寸,resolution 应该用 cc.game.canvas.width 和 cc.game.canvas.height。

除此之外,如果要得到你想要的效果,还需要针对 Sprite 的 box 进行约束。

下面是一个用于 web 的转换游戏坐标到 GL 坐标的

    function convertToGL (x, y) {
        var scaleX = cc.game.canvas.width / cc.visibleRect.width;
        var scaleY = cc.game.canvas.height / cc.visibleRect.height;
        return  cc.v2(x * scaleX, y * scaleY);
    }

用这个方法获得 sprite 在 GL 坐标系下的 x, y, width, height,传给 fragment shader

vec2 position = (((gl_FragCoord.xy - spriteXY) / spriteSize) * 2. - 1.) * vec2(resolution.x / resolution.y, 1.0);

大概应该是这样算的

1赞

熊猫大神,我明白你的意思,但是试了一下,还是有点问题,还是坐标转换不对,模拟器上随着我拖拽窗口大小绘制的内容始终在一个固定的位置,还是没有框在精灵里。求再帮忙解答一下,不胜感激!。
拖拽调整尺寸:


  1. 问题:cc.game.canvas 在 js里取不到,提示 cc.game.canvas isundefined(但是代码提示里有这个属性)

  2. 问题:canvas的大小是编辑器里设置的尺寸吗,我假设 visibleSize和canvas大小(960640)一样的话,
    我的精灵大小800
    480,精灵在屏幕正中央
    那我在片段着色器里
    vec2 position = (((gl_FragCoord.xy - vec2(0.0,0.0)) / vec2(800,480)) * 2. - 1.) * vec2(960 / 640, 1.0);
    position ,
    但是最后结果显示还是不对,这些都是在模拟器上运行的.
    我上传一个我这测试的代码,能劳烦看一下吗ShaderTest.zip (558.7 KB)


我又试了一下:resolution设置为画布大小
vec2 position = ((gl_FragCoord.xy / resolution) * 2. - 1.) * vec2(resolution.x / resolution.y, 1.0);
之后,果然图像显示在窗口中心了。
现在就是精灵的坐标转换没太明白,上面的1问题canvas的大小怎么取呢,cc.game.canvas不好使啊。能给个示例吗?

自己2了,已经解决了!稍后会写一个demo发出来…好鄙视自己的脑子

后来的问题还没来得及看,欢迎发 demo

等楼主的demo,谢谢

关注,等楼主的demo,谢谢