片段着色器中的循环不起作用

For loop in frag shader don't work

我试图在我的片段着色器中渲染多个粒子,但 600 个中只显示了两个。有人可以帮助我了解发生了什么吗?

shader.frag

#version 120

uniform sampler2DRect texture2;
uniform float iTime;
uniform vec2 iResolution;

#define M_PI 3.1415926535897932384626433832795

float random(vec2 co){

    float a = 12.9898;
    float b = 78.233;
    float c = 43758.5453;
    float dt= dot(co.xy ,vec2(a,b));
    float sn= mod(dt,3.14);
    return fract(sin(sn) * c);
}

void main(void){

    vec4 outColor = vec4(0.0, 0.0,0.0,1.0);
    float time = iTime * 0.1;
    vec2 uvNorm = gl_FragCoord.xy / iResolution.xy;
    vec2 uv = -0.5 + 1.0 * uvNorm;
    uv /= vec2(iResolution.y / iResolution.x, 1.);
   
    for(float i=0.0; i<600.0 ;i++){
    
        float f1 = mod(i * 0.101213, 0.28);
        float fft = texture2DRect(texture2, vec2(f1)).x;
        float r = (fft/10.0);
        float a = random(vec2(i))*(M_PI*2.);
    
        vec2 center = vec2(cos(a), sin(a)) * r/1.2;
        float dist = length(uv - center);
        float birghtness = 1./pow(0.01 + dist*250., 2.);
    
        vec3 color = vec3(fft-0.1, 1.0, fft-0.2);
        vec3 col = color* birghtness/2.0 * fft * 2.;
        col += color * birghtness * fft * 1.5;
        outColor.rgb += col;
     }

   gl_FragColor = outColor;
}

我是 openGL 的新手,之前我遇到过一些关于不同版本 openGL 的问题。这会是类似的东西吗?

粒子聚集在一个小区域内。将粒子数从 600 减少到例如50,你可以看到分离的颗粒。

for(float i=0.0; i<50.0 ;i++){ 
    ....

而且粒子显示的区域很小。您缩放半径,以扩大绘制粒子的区域:

vec2 uvNorm = gl_FragCoord.xy / iResolution.xy;
vec2 uv = (uvNorm - 0.5) * vec2(iResolution.x / iResolution.y, 1.0);
uv *= 0.3; // scale


请注意,您不使用变量 iTime/time。这可能会导致粒子挤在一起,因为你只显示一个初始状态。
我不知道初始算法中时间是如何使用的,因为你没有 post 参考。但是我把它放在某个地方,在代码片段中看到结果:

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

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

var Texture = {};
Texture.HandleLoadedTexture2D = function( image, texture, flipY ) {
    gl.activeTexture( gl.TEXTURE0 );
    gl.bindTexture( gl.TEXTURE_2D, texture );
    gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image );
    if ( flipY != undefined && flipY == true )
      gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, true );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT );
   gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT );
    gl.bindTexture( gl.TEXTURE_2D, null );
    return texture;
}
Texture.LoadTexture2D = function( name ) {
    var texture = gl.createTexture();
    texture.image = new Image();
    texture.image.setAttribute('crossorigin', 'anonymous');
    texture.image.onload = function () {
        Texture.HandleLoadedTexture2D( texture.image, texture, true )
    }
    texture.image.src = name;
    return texture;
}

var timing = {};

timing.prevTimeAbs = 0;
timing.pause = 0;
timing.deltaTimeLastMs = 0;
timing.deltaTimeAbsMs = 0;

timing.init =  function() {
  this.prevTimeAbs = Date.now();
  this.pause = 0;
  this.deltaTimeLastMs = 0;
  this.deltaTimeAbsMs = 0;
};

timing.calcDeltaTimes = function() {
  var currentTimeAbs = Date.now();
  var delta = currentTimeAbs - this.prevTimeAbs;
  this.prevTimeAbs = currentTimeAbs;
  this.deltaTimeLastMs = this.pause == 0 ? delta : 0;
  this.deltaTimeAbsMs += this.deltaTimeLastMs;
  return this.deltaTimeAbsMs;
};

       
function drawScene(){

    var canvas = document.getElementById( "camera-canvas" );
    var vp = [canvas.width, canvas.height];
    var pastTime = timing.calcDeltaTimes() / 1000.0;
   
    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 );
    var texUnit = 0;
    gl.activeTexture( gl.TEXTURE0 + texUnit );
    gl.bindTexture( gl.TEXTURE_2D, textureObj );
    ShaderProgram.Use( progDraw );
    ShaderProgram.SetUniformF1( progDraw, "iTime", pastTime );
    ShaderProgram.SetUniformF2( progDraw, "iResolution", vp );
    ShaderProgram.SetUniformI1( progDraw, "texture2", texUnit );
    VertexBuffer.Draw( bufRect );
}  

var gl;
var prog;
var bufObj = {};
var textureObj;
var maskTextureObj;
function sceneStart() {

    var canvas = document.getElementById( "camera-canvas");
    gl = canvas.getContext( "experimental-webgl" );
    //gl = canvas.getContext( "webgl2" );
    if ( !gl )
      return;

    var texCX = 128;
    var texCY = 128;
    var texPlan = [];
    for (ix = 0; ix < texCX; ++ix) {
        for (iy = 0; iy < texCY; ++iy) {
            var val_x = Math.sin( Math.PI * 6.0 * ix / texCX )
            var val_y = Math.sin( Math.PI * 6.0 * iy / texCY )
            texPlan.push( 128 + 127 * val_x, 63, 128 + 127 * val_y, 255 );
        }
    }
    
    textureObj = Texture.LoadTexture2D( "https://raw.githubusercontent.com/Rabbid76/graphics-snippets/master/resource/texture/supermario.jpg" );
      
    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;

    bufRect = VertexBuffer.Create(
    [ { data :  [ -1, -1, 1, -1, 1, 1, -1, 1 ], attrSize : 2, attrLoc : progDraw.inPos } ],
      [ 0, 1, 2, 0, 2, 3 ] );

    timing.init();
    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, 0.0, 1.0 );
    }
</script>

<script id="draw-shader-fs" type="x-shader/x-fragment">
    precision mediump float;

    varying vec2      vertPos;
    uniform float     iTime;
    uniform vec2      iResolution;
    uniform sampler2D texture2;
    
    #define M_PI 3.1415926535897932384626433832795
    
    float random(vec2 co){
    
        float a = 12.9898;
        float b = 78.233;
        float c = 43758.5453;
        float dt= dot(co.xy ,vec2(a,b));
        float sn= mod(dt,3.14);
        return fract(sin(sn) * c);
    }
    
    void main(void){
    
        vec4 outColor = vec4(0.0, 0.0,0.0,1.0);
        float time = iTime * 0.1;
        vec2 uvNorm = gl_FragCoord.xy / iResolution.xy;
        vec2 uv = (uvNorm - 0.5) * vec2(iResolution.x / iResolution.y, 1.0);
        uv *= 0.25; // scale 
    
        //for(float i=0.0; i<600.0 ;i++){
        for(float i=0.0; i<30.0 ;i++){  
    
            float f1 = mod(sin(time) * i * 0.101213, 0.28);
            float fft = texture2D(texture2, vec2(f1)).x;
            float r = (fft/10.0);
            float a = random(vec2(i,i))*(M_PI*2.);
    
            vec2 center = vec2(cos(a), sin(a)) * r/1.2;
            float dist = length(uv - center);
            float birghtness = 1./pow(0.01 + dist*250., 2.);
    
            vec3 color = vec3(fft-0.1, 1.0, fft-0.2);
            vec3 col = color* birghtness/2.0 * fft * 2.;
            col += color * birghtness * fft * 1.5;
            outColor.rgb += col;
         }
    
       gl_FragColor = outColor;
    }
</script>

<body onload="sceneStart();">
    <canvas id="camera-canvas" style="border: none;" width="512" height="512"></canvas>
</body>