2017-12-07 14 views
0

放射状のグラデーションシェーダを作成しようとしていますが、以下のイメージと似ています。線形および放射状のグラデーションミックスシェーダ

enter image description here

背景直線勾配はうまく動作しますが、私は放射状グラデーションでそれをミックスしようとすると、私は一番下にバブルを取得します。赤い背景は、y軸をさらに下に滑っているようです。

放射状の形状が背景に影響しないように2勾配をオーバーレイする方法はありますか?

また、htmlページの背景(青色)がキャンバスから見えるように見えます。どうすればそれを止めることができますか?

以下は、結果とコードスニペットのスクリーンショットです。

enter image description here

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", [512.0, 512.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() 
 
    { 
 
     float y = gl_FragCoord.y/resolution.y; 
 

 
    vec4 color0= vec4(0.0, 0.0,0.0, 1.0); 
 
    vec4 color1= vec4(0.15, 0.0,0.0, 1.0); 
 
    vec4 color2= vec4(0.7, 0.0,0.0, 1.0); 
 
    vec4 color3= vec4(1, 0.0,0.0, 1.0); 
 
    vec4 color4= vec4(1, 0.0,0.0, 1.0); 
 
    float step0 = 0.0; 
 
    float step1 = 0.15; 
 
    float step2 = 0.75; 
 
    float step3 = 0.95; 
 
    float step4 = 1.0; 
 
\t vec4 bg_color = mix(color0, color1, smoothstep(step0, step1, y)); 
 
\t bg_color = mix(bg_color, color2, smoothstep(step1, step2, y)); 
 
\t bg_color = mix(bg_color, color3, smoothstep(step2, step3, y)); 
 
\t bg_color = mix(bg_color, color4, smoothstep(step3, step4, y)); 
 

 
    float d = distance(resolution.xy*0.5,gl_FragCoord.xy)*0.005; 
 
    vec4 r_color0= vec4(1.0, 1.0,1.0, 1.0); 
 
    vec4 r_color1= vec4(1.0, 1.0,1.0, 0.2); 
 
    vec4 r_color2= vec4(1.0, 1.0,1.0, 1.0); 
 
    vec4 r_color3= vec4(1.0, 1.0,1.0, 0.1); 
 
    vec4 r_color4= vec4(1.0, 1.0,1.0, 1.0); 
 
    float r_step0 = 1.0; 
 
    float r_step1 = 0.9; 
 
    float r_step2 = 0.85; 
 
    float r_step3 = 0.05; 
 
    float r_step4 = 0.0; 
 

 
    vec4 r_color = mix(r_color0, r_color1, smoothstep(r_step0, r_step1, d)); 
 
    r_color = mix(r_color, r_color2, smoothstep(r_step1, r_step2, d)); 
 
    r_color = mix(r_color, r_color3, smoothstep(r_step2, r_step3, d)); 
 
    r_color = mix(r_color, r_color4, smoothstep(r_step3, r_step4, d)); 
 

 
    bg_color.a = 1.0; 
 

 

 
     gl_FragColor = mix(r_color, bg_color, d); 
 
    } 
 
    </script> 
 
    <style> 
 
    body{ 
 
    background:blue; 
 
    } 
 
    </style> 
 
    <body onload="sceneStart();"> 
 
     <canvas id="ogl-canvas" style="border: none;" width="512" height="512"></canvas> 
 
    </body>

答えて

0

GLSL mix(x, y, y)によって実現される式である:

x⋅(1−a)+y⋅ax⋅(1−a)+y⋅a 

これはaは範囲[0.0、1.0]であるべきであることを意味します。 Thsiは、clamp(a,0.0,1.0)によって賄うことができます。

このようなあなたのコードを適応:

gl_FragColor = vec4(mix(r_color.rgba, bg_color.rgba, clamp(d,0.0,1.0))); 

たぶん、あなたは、あなたが望む結果を達成するためにアルファチャンネルでdevideする必要があります。

gl_FragColor.rgb /= gl_FragColor.a; 


は、コードスニペットを参照してください、左側は問題の元のコードの結果を示し、右側は適合コードを示しています。

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]; 
 
    var div_alpha = document.getElementById("alpha").checked; 
 

 
    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", [512.0, 512.0]) 
 
    ShaderProgram.SetUniformF1(progDraw, "div_alpha", div_alpha) 
 
    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; 
 
    uniform float div_alpha; 
 

 
    void main() 
 
    { 
 
     float y = gl_FragCoord.y/resolution.y; 
 

 
    vec4 color0= vec4(0.0, 0.0,0.0, 1.0); 
 
    vec4 color1= vec4(0.15, 0.0,0.0, 1.0); 
 
    vec4 color2= vec4(0.7, 0.0,0.0, 1.0); 
 
    vec4 color3= vec4(1, 0.0,0.0, 1.0); 
 
    vec4 color4= vec4(1, 0.0,0.0, 1.0); 
 
    float step0 = 0.0; 
 
    float step1 = 0.15; 
 
    float step2 = 0.75; 
 
    float step3 = 0.95; 
 
    float step4 = 1.0; 
 
\t vec4 bg_color = mix(color0, color1, smoothstep(step0, step1, y)); 
 
\t bg_color = mix(bg_color, color2, smoothstep(step1, step2, y)); 
 
\t bg_color = mix(bg_color, color3, smoothstep(step2, step3, y)); 
 
\t bg_color = mix(bg_color, color4, smoothstep(step3, step4, y)); 
 

 
    float d = distance(resolution.xy*0.5,gl_FragCoord.xy)*0.005; 
 
    vec4 r_color0= vec4(1.0, 1.0,1.0, 1.0); 
 
    vec4 r_color1= vec4(1.0, 1.0,1.0, 0.2); 
 
    vec4 r_color2= vec4(1.0, 1.0,1.0, 1.0); 
 
    vec4 r_color3= vec4(1.0, 1.0,1.0, 0.1); 
 
    vec4 r_color4= vec4(1.0, 1.0,1.0, 1.0); 
 
    float r_step0 = 1.0; 
 
    float r_step1 = 0.9; 
 
    float r_step2 = 0.85; 
 
    float r_step3 = 0.05; 
 
    float r_step4 = 0.0; 
 

 
    vec4 r_color = mix(r_color0, r_color1, smoothstep(r_step0, r_step1, d)); 
 
    r_color = mix(r_color, r_color2, smoothstep(r_step1, r_step2, d)); 
 
    r_color = mix(r_color, r_color3, smoothstep(r_step2, r_step3, d)); 
 
    r_color = mix(r_color, r_color4, smoothstep(r_step3, r_step4, d)); 
 

 
    bg_color.a = 1.0; 
 

 
    vec4 orig_col = mix(r_color, bg_color, d); // original 
 
    vec4 new_col; 
 

 
    // new_col = vec4(mix(r_color.rgb/r_color.a, bg_color.rgb, clamp(d,0.0,1.0)), r_color.a); 
 
    new_col = vec4(mix(r_color.rgba, bg_color.rgba, clamp(d,0.0,1.0))); 
 
    new_col.rgb /= mix(1.0,new_col.a,div_alpha); 
 
    
 
    gl_FragColor = mix(orig_col, new_col, step(0.0, vertPos.x)) * step(0.0,abs(vertPos.x)-0.01); 
 
} 
 
</script> 
 

 
<body onload="sceneStart();"> 
 
     <div style="margin-left: 520px;"> 
 
     <div style="float: right; width: 100%;"> 
 
      <form name="inputs"> 
 
       <table> 
 
        <tr> <td> devide by alpha </td> 
 
         <td> <input type="checkbox" id="alpha" value="1" /></td></tr> 
 
       </table> 
 
      </form> 
 
     </div> 
 
     <div style="float: right; width: 520px; margin-left: -520px; background-color: blue;"> 
 
      <canvas id="ogl-canvas" style="border: none;" width="512" height="512"></canvas> 
 
     </div> 
 
     <div style="clear: both;"></div> 
 
    </div> 
 
</body>

関連する問題