ShadowGun的天空盒shader

暗影之枪demo里面出来的shader,用双层的滚动模拟了天空云层的流动。



CCEffect %{
  techniques:
  - name: opaque
    passes:
    - vert: unlit-vs:vert
      frag: unlit-fs:frag
      properties: &props
        color:        { value: [0.5, 0.5, 0.5, 0.5], inspector: { type: color } }
        tilingOffset: { value: [1, 0, 1, 0] }
        multiplier:   { value: 0.5 }
        mainTexture:  { value: grey         }
        detailTex:    { value: grey         }
  - name: transparent
    passes:
    - vert: unlit-vs:vert
      frag: unlit-fs:frag
      blendState:
        targets:
        - blend: true
          blendSrc: src_alpha
          blendDst: one_minus_src_alpha
          blendSrcAlpha: src_alpha
          blendDstAlpha: one_minus_src_alpha
      properties: *props
}%

CCProgram unlit-vs %{
  precision mediump float;
  #include <cc-global>
  #include <cc-local-batch>
  #include <input>

  #if USE_VERTEX_COLOR
    in vec4 a_color;
    out vec4 v_color;
  #endif

  #if USE_TEXTURE
    in vec2 a_texCoord;
    out vec4 v_uv;
    out float mul;
    uniform TexCoords {
      vec4 tilingOffset;
      float multiplier;
    };
  #endif

  highp vec4 vert () {
    vec4 position;
    CCVertInput(position);

    highp mat4 matWorld;
    CCGetWorldMatrix(matWorld);

    highp vec4 pos = cc_matProj * (cc_matView * matWorld) * position;

    #if USE_TEXTURE
      v_uv.xy = a_texCoord;
      v_uv.zw = a_texCoord;
      #if FLIP_UV
        v_uv.y = 1.0 - v_uv.y;
        v_uv.w = 1.0 - v_uv.w;
      #endif
      v_uv.xy += fract(tilingOffset.xy * cc_time.x);
      v_uv.zw += fract(tilingOffset.zw * cc_time.x);
      mul = multiplier;
    #endif

    #if USE_VERTEX_COLOR
      v_color = a_color;
    #endif

    return pos;
  }
}%

CCProgram unlit-fs %{
  precision mediump float;
  #include <output>

  #if USE_TEXTURE
    in vec4 v_uv;
    in float mul;
    uniform sampler2D mainTexture;
    uniform sampler2D detailTex;
  #endif

  #if USE_COLOR
    uniform Constant {
      vec4 color;
    };
  #endif

  #if USE_VERTEX_COLOR
    in vec4 v_color;
  #endif

  vec4 frag () {
    vec4 o = vec4(1, 1, 1, 1);

    #if USE_TEXTURE
      o *= texture(mainTexture, v_uv.xy) * texture(detailTex, v_uv.zw);
    #endif

    #if USE_COLOR
      o *= color * mul;
    #endif

    #if USE_VERTEX_COLOR
      o *= v_color;
    #endif

    return CCFragOutput(o);
  }
}%

很简单的处理,就是用了双贴图,然后在渲染的时候,做了叠加。
效果却很棒。。


skybox.zip (114.5 KB)

用到的模型,贴图跟shader都在zip包里面


使用办法:

  1. 在项目资源里创建一个Effect文件,然后把上面的的shader代码全放进去
  2. 再创建一个Material文件,然后选中Material文件,在右边属性栏处,Effect选择第1步创建的Effect
  3. 再把贴图拉进MainTexture里面。其它参数可以自行修改试试,会出现不同的效果。
  4. 最后再把这个材质拉到你的对象材质上。
11赞

请问怎么做天空盒子?

正常的天空盒你按 天空盒 去制作就行了。
这个天空盒其实就是个模型,需要你把相机的可视距离调到足够长。

你好 我觉得你的帖子都挺不错的,请问可以允许我转载到微信小游戏交流社区吗或者邀请您也在微信小游戏交流社区做分享。链接是https://developers.weixin.qq.com/community/minigame

收藏~

楼主你好~我想把它用在cocos creator上。有一些include只有c3d而cc没有,因此改动了一些代码;得出来的效果是只有一瓣的区域有显示。您知道大概是哪里出问题了么?

嗯,解决了,跟代码无关。选中两张天空贴图,属性编辑器里将WrapMode改成Repeat开启平铺模式就行了。
//////////
再请教一下,如果天空盒放在场景里由主摄像机渲染,那天空盒要很大、盖住整个场景;摄像机的视距也要调得很远。如果天空盒用另外一个坐标固定、角度跟随的单独摄像机渲染可以么?开销会更大么?

:grin: 开销这东西,你得请教下引擎的大佬们了。。

这个能优化下吗 效果不错 只是在微信小游戏上 如果机器帧数只有20-30帧的时候 云层会一卡一卡的移动

很强!:ox::beer:

1赞