ios 如何在 OpenGL ES 2.0 中获得“发光”着色器效果?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8166384/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 15:26:40  来源:igfitidea点击:

How to get a "Glow" shader effect in OpenGL ES 2.0?

iosopengl-esglslopengl-es-2.0shader

提问by st4wik

I'm writing a 3D app for iOS. I'm new to OpenGL ES 2.0, so I'm still getting myself around writing basic shaders. I really need to implement a "Glow" effect on some of my models, based on the texturing.

我正在为 iOS 编写 3D 应用程序。我是 OpenGL ES 2.0 的新手,所以我仍然在编写基本的着色器。我真的需要根据纹理在我的一些模型上实现“发光”效果。

Here's a sample:

这是一个示例:

Bloom/Glow from www.skillmanmedia.com/realbasic/bloomsnapshot.jpg.

Bloom/Glow 来自 www.skillmanmedia.com/realbasic/bloomsnapshot.jpg.

I'm looking for code examples for OpenGL ES2.0. Most code I find on the internet is either for desktop OpenGL or D3D.

我正在寻找 OpenGL ES2.0 的代码示例。我在互联网上找到的大多数代码都是用于桌面 OpenGL 或 D3D。

Any ideas?

有任何想法吗?

回答by Rabbid76

First of all there are tons of algorithms and techniques to generate a glow effect. I just want to present one possibility.

首先,有大量的算法和技术可以产生发光效果。我只想提出一种可能性。

Create a Material that is luminescent. For this I use a modified Blinn-Phonglight model, where the direction to the light source is always the inverse direction of the normal vector of the fragment.

创建发光的材质。为此,我使用了修改后的Blinn-Phong光模型,其中光源的方向始终是片段法向量的反方向。

varying vec3 vertPos;
varying vec3 vertNV;
varying vec3 vertCol;

uniform float u_glow;

void main()
{
    vec3 color = vertCol;

    float shininess = 10.0;
    vec3  normalV = normalize( vertNV );
    vec3  eyeV    = normalize( -vertPos );
    vec3  halfV   = normalize( eyeV + normalV );
    float NdotH   = max( 0.0, dot( normalV, halfV ) );
    float glowFac = ( shininess + 2.0 ) * pow( NdotH, shininess ) / ( 2.0 * 3.14159265 );

    fragColor = vec4( u_glow * (0.1 + color.rgb * glowFac * 0.5), 1.0 );
}

In a second step a gaussian blur algorithm is performed on the output. The scene is written to frame buffer with a texture bound to the color plane. A screen space pass uses the texture as the input to blur the output.
For performance reasons, the blur algorithm is first performed along the X-axis of the viewport and in a further step along the Y-axis of the viewport.

在第二步中,对输出执行高斯模糊算法。场景被写入帧缓冲区,纹理绑定到颜色平面。屏幕空间通道使用纹理作为输入来模糊输出。
出于性能原因,模糊算法首先沿视口的 X 轴执行,然后再沿视口的 Y 轴执行。

varying vec2 vertPos;
uniform sampler2D u_textureCol;
uniform vec2 u_textureSize;
uniform float u_sigma;
uniform int u_width;

float CalcGauss( float x, float sigma ) 
{
  float coeff = 1.0 / (2.0 * 3.14157 * sigma);
  float expon = -(x*x) / (2.0 * sigma);
  return (coeff*exp(expon));
}

void main()
{
    vec2 texC = vertPos.st * 0.5 + 0.5;
    vec4 texCol = texture( u_textureCol, texC );
    vec4 gaussCol = vec4( texCol.rgb, 1.0 );
    vec2 step = 1.0 / u_textureSize;
    for ( int i = 1; i <= u_width; ++ i )
    {
        vec2 actStep = vec2( float(i) * step.x, 0.0 );   // this is for the X-axis
        // vec2 actStep = vec2( 0.0, float(i) * step.y );   this would be for the Y-axis

        float weight = CalcGauss( float(i) / float(u_width), u_sigma );
        texCol = texture2D( u_textureCol, texC + actStep );    
        gaussCol += vec4( texCol.rgb * weight, weight );
        texCol = texture2D( u_textureCol, texC - actStep );
        gaussCol += vec4( texCol.rgb * weight, weight );
    }
    gaussCol.rgb /= gaussCol.w;
    gl_FragColor = vec4( gaussCol.rgb, 1.0 );
}

For the implementation of a blur algorithm see also the answer to the questions:

对于模糊算法的实现,另见问题的答案:

See the following similar WebGL example which puts all together:

请参阅以下类似的 WebGL 示例,它们将所有内容放在一起:

var readInput = true;
function changeEventHandler(event){
    readInput = true;
}
  
(function loadscene() {
  
  var resize, gl, progDraw, progBlurX, progPost, vp_size, blurFB;
  var bufCube = {};
  var bufQuad = {};
  var shininess = 10.0;
  var glow = 10.0;
  var sigma = 0.8;
  
  function render(delteMS){

      //if ( readInput ) {
          readInput = false;
          var sliderScale = 100;
          shininess = document.getElementById( "shine" ).value;
          glow      = document.getElementById( "glow" ).value / sliderScale;
          sigma     = document.getElementById( "sigma" ).value / sliderScale;
      //}

      Camera.create();
      Camera.vp = vp_size;
          
      gl.enable( gl.DEPTH_TEST );
      gl.clearColor( 0.0, 0.0, 0.0, 1.0 );
      gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );

      // set up framebuffer
      gl.bindFramebuffer( gl.FRAMEBUFFER, blurFB[0] );
      gl.viewport( 0, 0, blurFB[0].width, blurFB[0].height );
      gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
  
      // set up draw shader
      ShaderProgram.Use( progDraw.prog );
      ShaderProgram.SetUniformM44( progDraw.prog, "u_projectionMat44", Camera.Perspective() );
      ShaderProgram.SetUniformM44( progDraw.prog, "u_viewMat44", Camera.LookAt() );
      var modelMat = IdentityMat44()
      modelMat = RotateAxis( modelMat, CalcAng( delteMS, 13.0 ), 0 );
      modelMat = RotateAxis( modelMat, CalcAng( delteMS, 17.0 ), 1 );
      ShaderProgram.SetUniformM44( progDraw.prog, "u_modelMat44", modelMat );
      ShaderProgram.SetUniformF1( progDraw.prog, "u_shininess", shininess );
      ShaderProgram.SetUniformF1( progDraw.prog, "u_glow", glow );
      
      // draw scene
      VertexBuffer.Draw( bufCube );

      // set blur-X framebuffer and bind frambuffer texture
      gl.bindFramebuffer( gl.FRAMEBUFFER, blurFB[1] );
      gl.viewport( 0, 0, blurFB[1].width, blurFB[1].height );
      gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
      var texUnit = 1;
      gl.activeTexture( gl.TEXTURE0 + texUnit );
      gl.bindTexture( gl.TEXTURE_2D, blurFB[0].color0_texture );

      // set up blur-X shader
      ShaderProgram.Use( progBlurX.prog );
      ShaderProgram.SetUniformI1( progBlurX.prog , "u_texture", texUnit )
      ShaderProgram.SetUniformF2( progBlurX.prog , "u_textureSize", vp_size );
      ShaderProgram.SetUniformF1( progBlurX.prog , "u_sigma", sigma )

      // draw full screen space
      gl.enableVertexAttribArray( progBlurX.inPos );
      gl.bindBuffer( gl.ARRAY_BUFFER, bufQuad.pos );
      gl.vertexAttribPointer( progBlurX.inPos, 2, gl.FLOAT, false, 0, 0 ); 
      gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, bufQuad.inx );
      gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
      gl.disableVertexAttribArray( progBlurX.inPos );

      // reset framebuffer and bind frambuffer texture
      gl.bindFramebuffer( gl.FRAMEBUFFER, null );
      gl.viewport( 0, 0, vp_size[0], vp_size[1] );
      gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
      texUnit = 2;
      gl.activeTexture( gl.TEXTURE0 + texUnit );
      gl.bindTexture( gl.TEXTURE_2D, blurFB[1].color0_texture );

      // set up pst process shader
      ShaderProgram.Use( progPost.prog );
      ShaderProgram.SetUniformI1( progPost.prog, "u_texture", texUnit )
      ShaderProgram.SetUniformF2( progPost.prog, "u_textureSize", vp_size );
      ShaderProgram.SetUniformF1( progPost.prog, "u_sigma", sigma );

      // draw full screen space
      gl.enableVertexAttribArray( progPost.inPos );
      gl.bindBuffer( gl.ARRAY_BUFFER, bufQuad.pos );
      gl.vertexAttribPointer( progPost.inPos, 2, gl.FLOAT, false, 0, 0 ); 
      gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, bufQuad.inx );
      gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
      gl.disableVertexAttribArray( progPost.inPos );

      requestAnimationFrame(render);
  }
  
  function resize() {
      //vp_size = [gl.drawingBufferWidth, gl.drawingBufferHeight];
      vp_size = [window.innerWidth, window.innerHeight]
      canvas.width = vp_size[0];
      canvas.height = vp_size[1];

      var fbsize = Math.max(vp_size[0], vp_size[1])-1;
      fbsize = 1 << 31 - Math.clz32(fbsize); // nearest power of 2
      fbsize = fbsize * 2

      blurFB = [];
      for ( var i = 0; i < 2; ++ i ) {
          fb = gl.createFramebuffer();
          fb.width = fbsize;
          fb.height = fbsize;
          gl.bindFramebuffer( gl.FRAMEBUFFER, fb );
          fb.color0_texture = gl.createTexture();
          gl.bindTexture( gl.TEXTURE_2D, fb.color0_texture );
          gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
          gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
          gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, fb.width, fb.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null );
          fb.renderbuffer = gl.createRenderbuffer();
          gl.bindRenderbuffer( gl.RENDERBUFFER, fb.renderbuffer );
          gl.renderbufferStorage( gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, fb.width, fb.height );
          gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fb.color0_texture, 0 );
          gl.framebufferRenderbuffer( gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, fb.renderbuffer );
          gl.bindTexture( gl.TEXTURE_2D, null );
          gl.bindRenderbuffer( gl.RENDERBUFFER, null );
          gl.bindFramebuffer( gl.FRAMEBUFFER, null );
          blurFB.push( fb );
      }
  }
  
  function initScene() {
  
      canvas = document.getElementById( "canvas");
      gl = canvas.getContext( "experimental-webgl" );
      if ( !gl )
        return null;
  
      progDraw = {}
      progDraw.prog = ShaderProgram.Create( 
        [ { source : "draw-shader-vs", stage : gl.VERTEX_SHADER },
          { source : "draw-shader-fs", stage : gl.FRAGMENT_SHADER }
        ] );
      if ( !progDraw.prog )
          return null;
      progDraw.inPos = gl.getAttribLocation( progDraw.prog, "inPos" );
      progDraw.inNV  = gl.getAttribLocation( progDraw.prog, "inNV" );
      progDraw.inCol = gl.getAttribLocation( progDraw.prog, "inCol" );

      progBlurX = {}
      progBlurX.prog = ShaderProgram.Create( 
        [ { source : "post-shader-vs", stage : gl.VERTEX_SHADER },
          { source : "blurX-shader-fs", stage : gl.FRAGMENT_SHADER }
        ] );
      progBlurX.inPos = gl.getAttribLocation( progBlurX.prog, "inPos" );
      if ( !progBlurX.prog )
          return;    

      progPost = {}
      progPost.prog = ShaderProgram.Create( 
        [ { source : "post-shader-vs", stage : gl.VERTEX_SHADER },
          { source : "blurY-shader-fs", stage : gl.FRAGMENT_SHADER }
        ] );
      progPost.inPos = gl.getAttribLocation( progPost.prog, "inPos" );
      if ( !progPost.prog )
          return;
      
      // create cube
      var cubePos = [
        -1.0, -1.0,  1.0,  1.0, -1.0,  1.0,  1.0,  1.0,  1.0, -1.0,  1.0,  1.0,
        -1.0, -1.0, -1.0,  1.0, -1.0, -1.0,  1.0,  1.0, -1.0, -1.0,  1.0, -1.0 ];
      var cubeCol = [ 1.0, 0.0, 0.0, 1.0, 0.5, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 ];
      var cubeHlpInx = [ 0, 1, 2, 3, 1, 5, 6, 2, 5, 4, 7, 6, 4, 0, 3, 7, 3, 2, 6, 7, 1, 0, 4, 5 ];  
      var cubePosData = [];
      for ( var i = 0; i < cubeHlpInx.length; ++ i ) {
        cubePosData.push( cubePos[cubeHlpInx[i]*3], cubePos[cubeHlpInx[i]*3+1], cubePos[cubeHlpInx[i]*3+2] );
      }
      var cubeNVData = [];
      for ( var i1 = 0; i1 < cubeHlpInx.length; i1 += 4 ) {
      var nv = [0, 0, 0];
      for ( i2 = 0; i2 < 4; ++ i2 ) {
          var i = i1 + i2;
          nv[0] += cubePosData[i*3]; nv[1] += cubePosData[i*3+1]; nv[2] += cubePosData[i*3+2];
      }
      for ( i2 = 0; i2 < 4; ++ i2 )
        cubeNVData.push( nv[0], nv[1], nv[2] );
      }
      var cubeColData = [];
      for ( var is = 0; is < 6; ++ is ) {
        for ( var ip = 0; ip < 4; ++ ip ) {
         cubeColData.push( cubeCol[is*3], cubeCol[is*3+1], cubeCol[is*3+2] ); 
        }
      }
      var cubeInxData = [];
      for ( var i = 0; i < cubeHlpInx.length; i += 4 ) {
        cubeInxData.push( i, i+1, i+2, i, i+2, i+3 );   
      }
      bufCube = VertexBuffer.Create(
      [ { data : cubePosData, attrSize : 3, attrLoc : progDraw.inPos },
        { data : cubeNVData,  attrSize : 3, attrLoc : progDraw.inNV },
        { data : cubeColData, attrSize : 3, attrLoc : progDraw.inCol } ],
        cubeInxData );

      bufQuad.pos = gl.createBuffer();
      gl.bindBuffer( gl.ARRAY_BUFFER, bufQuad.pos );
      gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( [ -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0 ] ), gl.STATIC_DRAW );
      bufQuad.inx = gl.createBuffer();
      gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, bufQuad.inx );
      gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( [ 0, 1, 2, 0, 2, 3 ] ), gl.STATIC_DRAW );  
        
      window.onresize = resize;
      resize();
      requestAnimationFrame(render);
  }
  
  function Fract( val ) { 
      return val - Math.trunc( val );
  }
  function CalcAng( deltaTime, intervall ) {
      return Fract( deltaTime / (1000*intervall) ) * 2.0 * Math.PI;
  }
  function CalcMove( deltaTime, intervall, range ) {
      var pos = self.Fract( deltaTime / (1000*intervall) ) * 2.0
      var pos = pos < 1.0 ? pos : (2.0-pos)
      return range[0] + (range[1] - range[0]) * pos;
  }    
  function EllipticalPosition( a, b, angRag ) {
      var a_b = a * a - b * b
      var ea = (a_b <= 0) ? 0 : Math.sqrt( a_b );
      var eb = (a_b >= 0) ? 0 : Math.sqrt( -a_b );
      return [ a * Math.sin( angRag ) - ea, b * Math.cos( angRag ) - eb, 0 ];
  }
  
  glArrayType = typeof Float32Array !="undefined" ? Float32Array : ( typeof WebGLFloatArray != "undefined" ? WebGLFloatArray : Array );
  
  function IdentityMat44() {
    var m = new glArrayType(16);
    m[0]  = 1; m[1]  = 0; m[2]  = 0; m[3]  = 0;
    m[4]  = 0; m[5]  = 1; m[6]  = 0; m[7]  = 0;
    m[8]  = 0; m[9]  = 0; m[10] = 1; m[11] = 0;
    m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
    return m;
  };
  
  function RotateAxis(matA, angRad, axis) {
      var aMap = [ [1, 2], [2, 0], [0, 1] ];
      var a0 = aMap[axis][0], a1 = aMap[axis][1]; 
      var sinAng = Math.sin(angRad), cosAng = Math.cos(angRad);
      var matB = new glArrayType(16);
      for ( var i = 0; i < 16; ++ i ) matB[i] = matA[i];
      for ( var i = 0; i < 3; ++ i ) {
          matB[a0*4+i] = matA[a0*4+i] * cosAng + matA[a1*4+i] * sinAng;
          matB[a1*4+i] = matA[a0*4+i] * -sinAng + matA[a1*4+i] * cosAng;
      }
      return matB;
  }
  
  function Cross( a, b ) { return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0], 0.0 ]; }
  function Dot( a, b ) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
  function Normalize( v ) {
      var len = Math.sqrt( v[0] * v[0] + v[1] * v[1] + v[2] * v[2] );
      return [ v[0] / len, v[1] / len, v[2] / len ];
  }
  
  var Camera = {};
  Camera.create = function() {
      this.pos    = [0, 3, 0.0];
      this.target = [0, 0, 0];
      this.up     = [0, 0, 1];
      this.fov_y  = 90;
      this.vp     = [800, 600];
      this.near   = 0.5;
      this.far    = 100.0;
  }
  Camera.Perspective = function() {
      var fn = this.far + this.near;
      var f_n = this.far - this.near;
      var r = this.vp[0] / this.vp[1];
      var t = 1 / Math.tan( Math.PI * this.fov_y / 360 );
      var m = IdentityMat44();
      m[0]  = t/r; m[1]  = 0; m[2]  =  0;                              m[3]  = 0;
      m[4]  = 0;   m[5]  = t; m[6]  =  0;                              m[7]  = 0;
      m[8]  = 0;   m[9]  = 0; m[10] = -fn / f_n;                       m[11] = -1;
      m[12] = 0;   m[13] = 0; m[14] = -2 * this.far * this.near / f_n; m[15] =  0;
      return m;
  }
  Camera.LookAt = function() {
      var mz = Normalize( [ this.pos[0]-this.target[0], this.pos[1]-this.target[1], this.pos[2]-this.target[2] ] );
      var mx = Normalize( Cross( this.up, mz ) );
      var my = Normalize( Cross( mz, mx ) );
      var tx = Dot( mx, this.pos );
      var ty = Dot( my, this.pos );
      var tz = Dot( [-mz[0], -mz[1], -mz[2]], this.pos ); 
      var m = IdentityMat44();
      m[0]  = mx[0]; m[1]  = my[0]; m[2]  = mz[0]; m[3]  = 0;
      m[4]  = mx[1]; m[5]  = my[1]; m[6]  = mz[1]; m[7]  = 0;
      m[8]  = mx[2]; m[9]  = my[2]; m[10] = mz[2]; m[11] = 0;
      m[12] = tx;    m[13] = ty;    m[14] = tz;    m[15] = 1; 
      return m;
  } 
  
  var ShaderProgram = {};
  ShaderProgram.Create = function( shaderList ) {
      var shaderObjs = [];
      for ( var i_sh = 0; i_sh < shaderList.length; ++ i_sh ) {
          var shderObj = this.CompileShader( shaderList[i_sh].source, shaderList[i_sh].stage );
          if ( shderObj == 0 )
              return 0;
          shaderObjs.push( shderObj );
      }
      var progObj = this.LinkProgram( shaderObjs )
      if ( progObj != 0 ) {
          progObj.attribIndex = {};
          var noOfAttributes = gl.getProgramParameter( progObj, gl.ACTIVE_ATTRIBUTES );
          for ( var i_n = 0; i_n < noOfAttributes; ++ i_n ) {
              var name = gl.getActiveAttrib( progObj, i_n ).name;
              progObj.attribIndex[name] = gl.getAttribLocation( progObj, name );
          }
          progObj.unifomLocation = {};
          var noOfUniforms = gl.getProgramParameter( progObj, gl.ACTIVE_UNIFORMS );
          for ( var i_n = 0; i_n < noOfUniforms; ++ i_n ) {
              var name = gl.getActiveUniform( progObj, i_n ).name;
              progObj.unifomLocation[name] = gl.getUniformLocation( progObj, name );
          }
      }
      return progObj;
  }
  ShaderProgram.AttributeIndex = function( progObj, name ) { return progObj.attribIndex[name]; } 
  ShaderProgram.UniformLocation = function( progObj, name ) { return progObj.unifomLocation[name]; } 
  ShaderProgram.Use = function( progObj ) { gl.useProgram( progObj ); } 
  ShaderProgram.SetUniformI1  = function( progObj, name, val ) { if(progObj.unifomLocation[name]) gl.uniform1i( progObj.unifomLocation[name], val ); }
  ShaderProgram.SetUniformF1  = function( progObj, name, val ) { if(progObj.unifomLocation[name]) gl.uniform1f( progObj.unifomLocation[name], val ); }
  ShaderProgram.SetUniformF2  = function( progObj, name, arr ) { if(progObj.unifomLocation[name]) gl.uniform2fv( progObj.unifomLocation[name], arr ); }
  ShaderProgram.SetUniformF3  = function( progObj, name, arr ) { if(progObj.unifomLocation[name]) gl.uniform3fv( progObj.unifomLocation[name], arr ); }
  ShaderProgram.SetUniformF4  = function( progObj, name, arr ) { if(progObj.unifomLocation[name]) gl.uniform4fv( progObj.unifomLocation[name], arr ); }
  ShaderProgram.SetUniformM33 = function( progObj, name, mat ) { if(progObj.unifomLocation[name]) gl.uniformMatrix3fv( progObj.unifomLocation[name], false, mat ); }
  ShaderProgram.SetUniformM44 = function( progObj, name, mat ) { if(progObj.unifomLocation[name]) gl.uniformMatrix4fv( progObj.unifomLocation[name], false, mat ); }
  ShaderProgram.CompileShader = function( source, shaderStage ) {
      var shaderScript = document.getElementById(source);
      if (shaderScript)
        source = shaderScript.text;
      var shaderObj = gl.createShader( shaderStage );
      gl.shaderSource( shaderObj, source );
      gl.compileShader( shaderObj );
      var status = gl.getShaderParameter( shaderObj, gl.COMPILE_STATUS );
      if ( !status ) alert(gl.getShaderInfoLog(shaderObj));
      return status ? shaderObj : null;
  } 
  ShaderProgram.LinkProgram = function( shaderObjs ) {
      var prog = gl.createProgram();
      for ( var i_sh = 0; i_sh < shaderObjs.length; ++ i_sh )
          gl.attachShader( prog, shaderObjs[i_sh] );
      gl.linkProgram( prog );
      status = gl.getProgramParameter( prog, gl.LINK_STATUS );
      if ( !status ) alert("Could not initialise shaders");
      gl.useProgram( null );
      return status ? prog : null;
  }
  
  var VertexBuffer = {};
  VertexBuffer.Create = function( attributes, indices ) {
      var buffer = {};
      buffer.buf = [];
      buffer.attr = []
      for ( var i = 0; i < attributes.length; ++ i ) {
          buffer.buf.push( gl.createBuffer() );
          buffer.attr.push( { size : attributes[i].attrSize, loc : attributes[i].attrLoc } );
          gl.bindBuffer( gl.ARRAY_BUFFER, buffer.buf[i] );
          gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( attributes[i].data ), gl.STATIC_DRAW );
      }
      buffer.inx = gl.createBuffer();
      gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, buffer.inx );
      gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( indices ), gl.STATIC_DRAW );
      buffer.inxLen = indices.length;
      gl.bindBuffer( gl.ARRAY_BUFFER, null );
      gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null );
      return buffer;
  }
  VertexBuffer.Draw = function( bufObj ) {
    for ( var i = 0; i < bufObj.buf.length; ++ i ) {
          gl.bindBuffer( gl.ARRAY_BUFFER, bufObj.buf[i] );
          gl.vertexAttribPointer( bufObj.attr[i].loc, bufObj.attr[i].size, gl.FLOAT, false, 0, 0 );
          gl.enableVertexAttribArray( bufObj.attr[i].loc );
      }
      gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, bufObj.inx );
      gl.drawElements( gl.TRIANGLES, bufObj.inxLen, gl.UNSIGNED_SHORT, 0 );
      for ( var i = 0; i < bufObj.buf.length; ++ i )
         gl.disableVertexAttribArray( bufObj.attr[i].loc );
      gl.bindBuffer( gl.ARRAY_BUFFER, null );
      gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null );
  }
  
  initScene();
  
})();
html,body {
    height: 100%;
    width: 100%;
    margin: 0;
    overflow: hidden;
}

#gui {
    position : absolute;
    top : 0;
    left : 0;
}
<script id="draw-shader-vs" type="x-shader/x-vertex">
    precision highp float;
    
    attribute vec3 inPos;
    attribute vec3 inNV;
    attribute vec3 inCol;
  
    varying vec3 vertPos;
    varying vec3 vertNV;
    varying vec3 vertCol;
    
    uniform mat4 u_projectionMat44;
    uniform mat4 u_viewMat44;
    uniform mat4 u_modelMat44;
    
    void main()
    {   
        mat4 mv       = u_viewMat44 * u_modelMat44; 
        vertCol       = inCol;
        vertNV        = normalize(mat3(mv) * inNV);
        vec4 viewPos  = mv * vec4( inPos, 1.0 );
        vertPos       = viewPos.xyz;
        gl_Position   = u_projectionMat44 * viewPos;
    }
</script>
  
<script id="draw-shader-fs" type="x-shader/x-fragment">
    precision mediump float;

    varying vec3 vertPos;
    varying vec3 vertNV;
    varying vec3 vertCol;
    
    uniform float u_shininess;
    uniform float u_glow;
    
    void main()
    {
        vec3 color = vertCol;
        vec3  normalV  = normalize( vertNV );
        vec3  eyeV     = normalize( -vertPos );
        vec3  halfV    = normalize( eyeV + normalV );
        float NdotH    = max( 0.0, dot( normalV, halfV ) );
        float shineFac = ( u_shininess + 2.0 ) * pow( NdotH, u_shininess ) / ( 2.0 * 3.14159265 );
        gl_FragColor   = vec4( u_glow*0.1 + color.rgb * u_glow * shineFac * 0.5, 1.0 );
    } 
</script>
  
<script id="post-shader-vs" type="x-shader/x-vertex">
    precision mediump float;
    
    attribute vec2 inPos;
    
    varying   vec2 pos;
    
    void main()
    {
        pos = inPos;
        gl_Position = vec4( inPos, 0.0, 1.0 );
    }
</script>
    
<script id="blurX-shader-fs" type="x-shader/x-fragment">
    precision mediump float;
    
    varying vec2 pos;
    
    uniform sampler2D u_texture;
    uniform vec2      u_textureSize;
    uniform float     u_sigma;
    
    float CalcGauss( float x, float sigma )
    {
      float coeff = 1.0 / (2.0 * 3.14157 * sigma);
      float expon = -(x*x) / (2.0 * sigma);
      return (coeff*exp(expon));
    }
    
    void main()
    {
        vec2 texC = pos.st * 0.5 + 0.5;
        vec4 texCol = texture2D( u_texture, texC );
        vec4 gaussCol = vec4( texCol.rgb, 1.0 );
        float stepX = 1.0 / u_textureSize.x;
        for ( int i = 1; i <= 20; ++ i )
        {
            float weight = CalcGauss( float(i) / 32.0, u_sigma * 0.5 );
            texCol = texture2D( u_texture, texC + vec2( float(i) * stepX, 0.0 ) );
            gaussCol += vec4( texCol.rgb * weight, weight );
            texCol = texture2D( u_texture, texC - vec2( float(i) * stepX, 0.0 ) );
            gaussCol += vec4( texCol.rgb * weight, weight );
        }
        gaussCol.rgb /= gaussCol.w;
        gl_FragColor = vec4( gaussCol.rgb, 1.0 );
    }
</script>
    
<script id="blurY-shader-fs" type="x-shader/x-fragment">
    precision mediump float;
    
    varying vec2 pos;
    
    uniform sampler2D u_texture;
    uniform vec2      u_textureSize;
    uniform float     u_sigma;
    
    float CalcGauss( float x, float sigma )
    {
      float coeff = 1.0 / (2.0 * 3.14157 * sigma);
      float expon = -(x*x) / (2.0 * sigma);
      return (coeff*exp(expon));
    }
    
    void main()
    {
        vec2 texC = pos.st * 0.5 + 0.5;
        vec4 texCol = texture2D( u_texture, texC );
        vec4 gaussCol = vec4( texCol.rgb, 1.0 );
        float stepY = 1.0 / u_textureSize.y;
        for ( int i = 1; i <= 20; ++ i )
        {
            float weight = CalcGauss( float(i) / 32.0, u_sigma * 0.5 );
            texCol = texture2D( u_texture, texC + vec2( 0.0, float(i) * stepY ) );
            gaussCol += vec4( texCol.rgb * weight, weight );
            texCol = texture2D( u_texture, texC - vec2( 0.0, float(i) * stepY ) );
            gaussCol += vec4( texCol.rgb * weight, weight );
        }
        vec3 hdrCol = 2.0 * gaussCol.xyz / gaussCol.w;
        vec3 mappedCol = vec3( 1.0 ) - exp( -hdrCol.rgb * 3.0 );
        gl_FragColor = vec4( clamp( mappedCol.rgb, 0.0, 1.0 ), 1.0 );
    }
</script>

<div>
    <form id="gui" name="inputs">
        <table>
            <tr> <td> <font color= #CCF>shininess</font> </td> 
                 <td> <input type="range" id="shine" min="0" max="50" value="10" onchange="changeEventHandler(event);"/></td> </tr>
            <tr> <td> <font color= #CCF>glow</font> </td> 
                 <td> <input type="range" id="glow" min="100" max="400" value="250" onchange="changeEventHandler(event);"/></td> </tr>
            <tr> <td> <font color= #CCF>blur</font> </td> 
                 <td> <input type="range" id="sigma" min="1" max="100" value="60" onchange="changeEventHandler(event);"/></td> </tr>
        </table>
    </form>
</div>

<canvas id="canvas" style="border: none;" width="100%" height="100%"></canvas>

回答by 010110110101

The website GLSL Sandboxhas a collection of shader examples. This one has the glow and appears to be able to compile for ES.

网站GLSL Sandbox有一系列着色器示例。 这个有亮点,似乎能够为 ES 编译

You should be able to modify these to pull uv's from your texture.

您应该能够修改这些以从您的纹理中提取 uv。

Here is some code directly from this site:

这是直接来自该站点的一些代码:

#ifdef GL_ES
precision mediump float;
#endif

#extension GL_OES_standard_derivatives : enable

uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;

void main(void){

    vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);
    vec3 color1 = vec3(0.0, 0.3, 0.5);
    vec3 color2 = vec3(0.5, 0.0, 0.3);

    float f = 0.0;
    float g = 0.0;
    float h = 0.0;
    float PI = 3.14159265;
    for(float i = 0.0; i < 40.0; i++){
        if (floor(mouse.x * 41.0) < i)
            break;
        float s = sin(time + i * PI / 20.0) * 0.8;
        float c = cos(time + i * PI / 20.0) * 0.8;
        float d = abs(p.x + c);
        float e = abs(p.y + s);
        f += 0.001 / d;
        g += 0.001 / e;
        h += 0.00003 / (d * e);
    }


    gl_FragColor = vec4(f * color1 + g * color2 + vec3(h), 1.0);
}