【问题标题】:How to create a mutli-step radial gradient Fragment shader如何创建多步径向渐变片段着色器
【发布时间】:2018-06-03 15:25:54
【问题描述】:

我正在使用一些着色器代码通过混合颜色来创建多步线性渐变。它工作得很好。我有一个使用距离的径向着色器。工作正常,但我不知道将其调整为多步骤。

我该如何处理它?

线性渐变 http://glslsandbox.com/e#39992.0

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

void main( void ) {

    float y = gl_FragCoord.y / resolution.y;

    vec4 white = vec4(1.0, 1.0, 1.0, 1.0);
    vec4 red = vec4(1.0, 0.0, 0.0, 1.0);
    vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);
    vec4 green = vec4(0.0, 1.0, 0.0, 1.0);
    float step1 = 0.0;
    float step2 = 0.33;
    float step3 = 0.66;
    float step4 = 1.0;

    vec4 color = mix(white, red, smoothstep(step1, step2, y));
    color = mix(color, blue, smoothstep(step2, step3, y));
    color = mix(color, green, smoothstep(step3, step4, y));

    gl_FragColor = color;

}

简单的径向渐变 https://www.shadertoy.com/view/4tjSWh

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{

    float d = distance(iResolution.xy*0.5,fragCoord.xy)*(sin(1.0)+1.5)*0.003;
    fragColor = mix(vec4(1.0, 1.0, 1.0, 1.0), vec4(0.0, 0.0, 0.0, 1.0), d);
}

【问题讨论】:

    标签: glsl fragment-shader


    【解决方案1】:

    您只需计算当前片段到视口中心的距离。为此,您必须计算标准化设备坐标中的片段位置。您可以使用与“条形”着色器中的 y 坐标相同的方式使用到中心的距离:

    vec2 pos_ndc = 2.0 * gl_FragCoord.xy / resolution.xy - 1.0;
    float dist = length(pos_ndc);
    

    你的着色器应该看起来像这样:

    void main()
    {
        vec2 pos_ndc = 2.0 * gl_FragCoord.xy / resolution.xy - 1.0;
        float dist = length(pos_ndc);
    
        vec4 white = vec4(1.0, 1.0, 1.0, 1.0);
        vec4 red = vec4(1.0, 0.0, 0.0, 1.0);
        vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);
        vec4 green = vec4(0.0, 1.0, 0.0, 1.0);
        float step1 = 0.0;
        float step2 = 0.33;
        float step3 = 0.66;
        float step4 = 1.0;
    
        vec4 color = mix(white, red, smoothstep(step1, step2, dist));
        color = mix(color, blue, smoothstep(step2, step3, dist));
        color = mix(color, green, smoothstep(step3, step4, dist));
    
        gl_FragColor = color;
    }
    

    预览:


    见代码sn-p:

    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 = "";
            var node = shaderScript.firstChild;
            while (node) {
              if (node.nodeType == 3) source += node.textContent;
              node = node.nextSibling;
            }
          }
          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 : 0;
      } 
      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 : 0;
      }
              
      function drawScene(){
      
          var canvas = document.getElementById( "ogl-canvas" );
          var vp = [canvas.width, canvas.height];
          
          gl.viewport( 0, 0, canvas.width, canvas.height );
          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 );
          ShaderProgram.Use( progDraw );
          ShaderProgram.SetUniformF2( progDraw, "resolution", [256.0, 256.0] )
          gl.enableVertexAttribArray( progDraw.inPos );
          gl.bindBuffer( gl.ARRAY_BUFFER, bufObj.pos );
          gl.vertexAttribPointer( progDraw.inPos, 2, gl.FLOAT, false, 0, 0 ); 
          gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, bufObj.inx );
          gl.drawElements( gl.TRIANGLES, bufObj.inx.len, gl.UNSIGNED_SHORT, 0 );
          gl.disableVertexAttribArray( progDraw.pos );
      }  
      
      var gl;
      var prog;
      var bufObj = {};
      function sceneStart() {
      
          var canvas = document.getElementById( "ogl-canvas");
          gl = canvas.getContext( "experimental-webgl" );
          if ( !gl )
            return;
      
          progDraw = ShaderProgram.Create( 
            [ { source : "draw-shader-vs", stage : gl.VERTEX_SHADER },
              { source : "draw-shader-fs", stage : gl.FRAGMENT_SHADER }
            ] );
          progDraw.inPos = gl.getAttribLocation( progDraw, "inPos" );
          if ( prog == 0 )
              return;
      
          var pos = [ -1, -1, 1, -1, 1, 1, -1, 1 ];
          var inx = [ 0, 1, 2, 0, 2, 3 ];
          bufObj.pos = gl.createBuffer();
          gl.bindBuffer( gl.ARRAY_BUFFER, bufObj.pos );
          gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( pos ), gl.STATIC_DRAW );
          bufObj.inx = gl.createBuffer();
          bufObj.inx.len = inx.length;
          gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, bufObj.inx );
          gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( inx ), gl.STATIC_DRAW );
      
          setInterval(drawScene, 50);
      }
    <script id="draw-shader-vs" type="x-shader/x-vertex">
      precision mediump float;
      
      attribute vec2 inPos;
      
      varying vec2 vertPos;
      
      void main()
      {
          vertPos = inPos;
          gl_Position = vec4( inPos.xy, 0.0, 1.0 );
      }
      </script>
      
      <script id="draw-shader-fs" type="x-shader/x-fragment">
      precision mediump float;
      
      varying vec2 vertPos;
      uniform vec2 resolution;
    
    
        void main()
        {
          vec2 pos_ndc = 2.0 * gl_FragCoord.xy / resolution.xy - 1.0;
          float dist = length(pos_ndc);
          
          vec4 white = vec4(1.0, 1.0, 1.0, 1.0);
          vec4 red = vec4(1.0, 0.0, 0.0, 1.0);
          vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);
          vec4 green = vec4(0.0, 1.0, 0.0, 1.0);
          float step1 = 0.0;
          float step2 = 0.33;
          float step3 = 0.66;
          float step4 = 1.0;
    
          vec4 color = mix(white, red, smoothstep(step1, step2, dist));
          color = mix(color, blue, smoothstep(step2, step3, dist));
          color = mix(color, green, smoothstep(step3, step4, dist));
    
          gl_FragColor = color;
        }
      </script>
      
      <body onload="sceneStart();">
          <canvas id="ogl-canvas" style="border: none;" width="256" height="256"></canvas>
      </body>

    【讨论】:

      猜你喜欢
      • 2013-04-02
      • 2018-05-02
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多