<p>I wanna implement shadows example from  <a href="https://webgl2fundamentals.org/webgl/lessons/webgl-shadows.html" rel="nofollow noreferrer">webgl2fundamentals</a></p>
<p>also i a aware of framebuffer principe a have already working implementation of mirror projection.</p>
<p>Ignore VS extra vars .</p>
<p>I have trouble with shadows examples...</p>
<p>I always get black collor or error logs :</p>
<pre class="lang-json prettyprint-override"><code>GL_INVALID_OPERATION: Feedback loop formed between Framebuffer and active Texture.
</code></pre>
<p>My scene have two cubes. One <code>floor</code> and <code>myTextCube1</code> on top.</p>
<p>I added flag <code>object.shadows.FBO_IN_DRAW_PASS</code>.</p>
<p><strong>This is most important code from draw function:</strong>
DRAWER:</p>
<pre class="lang-js prettyprint-override"><code> ...

if(object.FBO &amp;&amp; object.shadows.FBO_IN_DRAW_PASS == true) {
    // test FBO
    let textureMatrix = m4.identity();
    textureMatrix = m4.translate(textureMatrix, 0.5, 0.5, 0.5);
    textureMatrix = m4.scale(textureMatrix, 0.5, 0.5, 0.5);
    textureMatrix = m4.multiply(textureMatrix, 
                     object.shadows.lightProjectionMatrix);

    const lightWorldMatrix = m4.lookAt(
        [ object.shadows.lightPosition[0],
          object.shadows.lightPosition[1],
          object.shadows.lightPosition[2]
        ],
        [object.shadows.lightTarget[0] ,
         object.shadows.lightTarget[1] , 
         object.shadows.lightTarget[2]  
        ], // target
        [object.shadows.orientation[0], object.shadows.orientation[1], object.shadows.orientation[2]], // up
            );
    textureMatrix = m4.multiply(textureMatrix, 
              m4.inverse(lightWorldMatrix));
    const mat = m4.multiply(lightWorldMatrix, 
              m4.inverse(object.shadows.lightProjectionMatrix));
    // draw to the depth texture
    world.GL.gl.uniform1i(object.shaderProgram.u_projectedTexture, false, 0);
            world.GL.gl.uniformMatrix4fv(object.shaderProgram.u_textureMatrix, false, textureMatrix);
            world.GL.gl.uniform3fv(object.shaderProgram.lightWorldPositionLocation, object.shadows.lightPosition);
    
            world.GL.gl.uniformMatrix4fv(object.shaderProgram.u_world, false,
                m4.translate(object.position.worldLocation[0],
                    object.position.worldLocation[1],
                    object.position.worldLocation[2])
            );
            // world.GL.gl.uniformMatrix4fv(object.shaderProgram.u_world, false, mat);
            world.GL.gl.uniform3fv(object.shaderProgram.u_reverseLightDirection, lightWorldMatrix.slice(8, 11));
            world.GL.gl.uniform1f(object.shaderProgram.u_bias, object.shadows.bias);

            //  console.log('LOG FBO TEXT ACTIVATE')
            world.GL.gl.activeTexture(world.GL.gl.TEXTURE0);
            world.GL.gl.bindTexture(world.GL.gl.TEXTURE_2D, object.FBO.deepTexture);
            world.GL.gl.uniform1i(object.shaderProgram.u_projectedTexture, 0);

        } else {
      // console.log('normal tex')
            for(var t = 0;t &lt; object.textures.length;t++) {
                if(object.custom.gl_texture == null) {
                    world.GL.gl.activeTexture(world.GL.gl['TEXTURE' + t]);
                    world.GL.gl.bindTexture(world.GL.gl.TEXTURE_2D, object.textures[t]);
                    world.GL.gl.pixelStorei(world.GL.gl.UNPACK_FLIP_Y_WEBGL, false);
                    if(object.texParams.MIPMAP == false) {
                        world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_S, object.texParams.TEXTURE_WRAP_S | world.GL.gl.REPEAT);
                        world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_T, object.texParams.TEXTURE_WRAP_T | world.GL.gl.REPEAT);
                        // -- Allocate storage for the texture
                        // world.GL.gl.texStorage2D(world.GL.gl.TEXTURE_2D, 1, world.GL.gl.RGB8, 512, 512);
                        // world.GL.gl.texSubImage2D(world.GL.gl.TEXTURE_2D, 0, 0, 0,512, 512, world.GL.gl.RGB, world.GL.gl.UNSIGNED_BYTE, object.textures[t]);
                    } else {
                        world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MAG_FILTER, object.texParams.TEXTURE_MAG_FILTER | world.GL.gl.LINEAR);
                        world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MIN_FILTER, object.texParams.TEXTURE_MIN_FILTER | world.GL.gl.LINEAR);
                        world.GL.gl.generateMipmap(world.GL.gl.TEXTURE_2D);
                    }

                    if(world.GL.extTFAnisotropic &amp;&amp; object.texParams.ANISOTROPIC == true) {
                        world.GL.gl.texParameterf(world.GL.gl.TEXTURE_2D,
                            world.GL.extTFAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT,
                            world.GL.MAX_TEXTURE_MAX_ANISOTROPY_EXT);
                    }
                    world.GL.gl.uniform1i(object.shaderProgram.samplerUniform, t);
                    world.GL.gl.uniform1i(object.shaderProgram.u_projectedTexture, 0);
                } else {
                    object.custom.gl_texture(object, t);
                }
            }
        }
 ...
     
</code></pre>
<pre class="lang-js prettyprint-override"><code>export const makeFBO2 = (gl, o) =&gt; {
    if(typeof o === 'undefined') {
        var o = {width: 512,    height: 512};
    }
    var error = function() {console.log('Error in creating FBO!'); return null;}
    var gl = world.GL.gl;
    const depthTexture = gl.createTexture();
    const depthTextureSize = 512;
    gl.bindTexture(gl.TEXTURE_2D, depthTexture);
    gl.texImage2D(
        gl.TEXTURE_2D,      // target
        0,                  // mip level
        gl.DEPTH_COMPONENT32F, // internal format
        depthTextureSize,   // width
        depthTextureSize,   // height
        0,                  // border
        gl.DEPTH_COMPONENT, // format
        gl.FLOAT,           // type
        null);              // data
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

    const depthFramebuffer = gl.createFramebuffer();
    gl.bindFramebuffer(gl.FRAMEBUFFER, depthFramebuffer);
    gl.framebufferTexture2D(
        gl.FRAMEBUFFER,       // target
        gl.DEPTH_ATTACHMENT,  // attachment point
        gl.TEXTURE_2D,        // texture target
        depthTexture,         // texture
        0);                   // mip level

    return [depthFramebuffer, depthTexture];
}
</code></pre>
<p>And also importan part of code is render:
RENDER</p>
<pre class="lang-js prettyprint-override"><code>
 
 
        world.GL.gl.bindFramebuffer(world.GL.gl.FRAMEBUFFER, world.FBOS[fbindex].FB);

        world.GL.gl.viewport(0, 0, 512, 512);
        world.GL.gl.clearColor(0.0, 1.0, 0.4, 1.0);
        world.GL.gl.clear(world.GL.gl.COLOR_BUFFER_BIT | world.GL.gl.DEPTH_BUFFER_BIT);
        world.GL.gl.enable(world.GL.gl.DEPTH_TEST);
        world.GL.gl.enable(world.GL.gl.CULL_FACE);
        world.GL.gl.disable(world.GL.gl.BLEND);

    // - draw all `non fbo` and `no blend`
    if(
                
                (world.contentList[looper].visible === true &amp;&amp;
                !world.contentList[looper].FBO &amp;&amp;
                world.contentList[looper].glBlend.blendEnabled == false) 
                 ||
                 (world.contentList[looper].visible === true &amp;&amp;
                    world.contentList[looper].shadows.FBO_IN_DRAW_PASS == false &amp;&amp;
                    world.contentList[looper].glBlend.blendEnabled == false)
            ) {

                    world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
                    world.drawCube(world.contentList[looper], 'noray');
                    world.contentList[looper].shadows.FBO_IN_DRAW_PASS = true;


}



    world.GL.gl.bindFramebuffer(world.GL.gl.FRAMEBUFFER, null);



    // All but no blend

        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
                world.contentList[looper].shadows.FBO_IN_DRAW_PASS = true;
                world.drawCube(world.contentList[looper]);
                world.animate(world.contentList[looper]);
                world.contentList[looper].shadows.FBO_IN_DRAW_PASS = false;







END OF REDER FUNC


App.operation.CameraPerspective = function() {
    this.GL.gl.viewport(0, 0, canvas.width, canvas.height);
    this.GL.gl.clear(this.GL.gl.COLOR_BUFFER_BIT | this.GL.gl.DEPTH_BUFFER_BIT);
    mat4.perspective(this.pMatrix, degToRad(App.camera.viewAngle), this.GL.gl.viewportWidth / this.GL.gl.viewportHeight, App.camera.nearViewpoint, App.camera.farViewpoint);
}
</code></pre>
<p><strong>And after all shaders part:</strong></p>
<pre class="lang-none prettyprint-override"><code>export function generateSpotLightShadowDefinitions() {
    return `// inject generateSpotLightShadowDefinitions
    uniform sampler2D u_projectedTexture;
    uniform sampler2D u_texture;
    in vec2 v_texcoord;
    uniform float u_bias;
    in vec4 v_projectedTexcoord;
    in vec3 v_surfaceToLight;
    in vec3 v_surfaceToView;
    uniform vec4 u_color;
    uniform float u_shininess;
    uniform vec3 u_lightDirection;
    uniform float u_innerLimit;
    uniform float u_outerLimit;
    uniform mat4 u_projection;
    uniform mat4 u_view;
    uniform mat4 u_world;
    uniform mat4 u_textureMatrix;
    uniform vec3 u_reverseLightDirection;
    `;
}

export function generateSpotLightShadowMain() {
    return `
    vec3 normal = normalize(v_normal);
    float light = dot(normal, u_reverseLightDirection);
    vec3 projectedTexcoord = v_projectedTexcoord.xyz / v_projectedTexcoord.w;
    float currentDepth = projectedTexcoord.z + u_bias;

    bool inRange =
            projectedTexcoord.x &gt;= 0.0 &amp;&amp;
            projectedTexcoord.x &lt;= 1.0 &amp;&amp;
            projectedTexcoord.y &gt;= 0.0 &amp;&amp;
            projectedTexcoord.y &lt;= 1.0;
    float projectedDepth = texture(u_projectedTexture, projectedTexcoord.xy).r;
    float shadowLight = (inRange &amp;&amp; projectedDepth &lt;= currentDepth) ? 0.0 : 1.0;
    vec4 texColor = texture(u_texture, v_texcoord) * vec4(1, 1, 1, 1);
    outColor = vec4(texColor.rgb * light * shadowLight , texColor.a);
    `;
}
</code></pre>
<p>VS GLSL:</p>
<pre class="lang-none prettyprint-override"><code>export function getInitVSCubeTexLight() {
  const f = `#version 300 es
  in vec3 aVertexPosition;
  in vec3 aVertexNormal;
  in vec2 aTextureCoord;
  uniform mat4 uMVMatrix;
  uniform mat4 uPMatrix;
  uniform mat3 uNMatrix;
  uniform vec3 uAmbientColor;
  uniform vec3 uLightingDirection;
  uniform vec3 uDirectionalColor;
  uniform bool uUseLighting;
  out vec2 vTextureCoord;
  out vec3 vLightWeighting;
  out vec3 meVertexPosition;
  uniform vec3 u_lightWorldPosition;
  out vec3 v_normal;
  out vec3 v_surfaceToLight;
  out vec3 v_surfaceToView;
  out mat4 uMVMatrixINTER;
  out mat3 uNMatrixINTER;
  out mat4 uPMatrixINNTER;
  in vec4 specularColor;
  out vec4 vColor;
  out vec3 vNormal;
  out vec4 vPosition;
  out float vDist;
  uniform mat4 u_textureMatrix;
  out vec2 v_texcoord;
  out vec4 v_projectedTexcoord;
  uniform mat4 u_world;

  void main(void) {
    meVertexPosition = aVertexPosition;
    uMVMatrixINTER = uMVMatrix;
    uNMatrixINTER = uNMatrix;
    uPMatrixINNTER = uPMatrix;
    vColor = specularColor;
    vNormal = normalize(mat3(u_world) * vec3(aVertexNormal)); 
    vPosition =  uMVMatrix * vec4(aVertexPosition, 1.0);
    vDist = gl_Position.w;
    v_normal = uNMatrix  *  vec3(aVertexNormal);
    vec3 surfaceWorldPosition = (uNMatrix * aVertexPosition).xyz;
    v_surfaceToLight = u_lightWorldPosition - surfaceWorldPosition;
    v_surfaceToView = (uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0)).xyz - surfaceWorldPosition;
    vec4 worldPosition =     vec4((uNMatrix * aVertexPosition).xyz, 1.0);
    v_texcoord = aTextureCoord;
   v_projectedTexcoord = u_textureMatrix * worldPosition;
    gl_Position   = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
    vTextureCoord = aTextureCoord;
    if (!uUseLighting) {
      vLightWeighting = vec3(1.0, 1.0, 1.0);
    } else {
      vec3 transformedNormal          = uNMatrix * aVertexNormal;
      float directionalLightWeighting = max(dot(transformedNormal, uLightingDirection), 0.0);
      vLightWeighting                 = uAmbientColor + uDirectionalColor * directionalLightWeighting;
    }
  }`;
    scriptManager.LOAD(f, &quot;cubeLightTex-shader-vs&quot;, &quot;x-shader/x-vertex&quot;, &quot;shaders&quot;)
}
</code></pre>
<p><a href="https://i.sstatic.net/OlSSgXx1.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/OlSSgXx1.png" alt="enter image description here" /></a></p>
<p>Any suggestion?
Looks like every cube for itself cast shadow no between cast...</p>
<p>If you wanna live demos of my library you can explore it <a href="https://maximumroulette.com/apps/matrix-engine/examples-build.html" rel="nofollow noreferrer">here</a>.</p>
<p>UPDATE:</p>
<p>I found at <a href="https://www.youtube.com/watch?v=0Xk96uN3Ceo&amp;ab_channel=SketchpunkLabs" rel="nofollow noreferrer">https://www.youtube.com/watch?v=0Xk96uN3Ceo&amp;ab_channel=SketchpunkLabs</a>
on 24:00 minute</p>
<pre><code>drawBuffers(gl.NONE)
readBuffer(gl.NONE)
</code></pre>
<p>I must try this lines...</p>
<p>Source code :
<a href="https://github.com/zlatnaspirala/matrix-engine" rel="nofollow noreferrer">github</a></p>
<p><a href="https://github.com/zlatnaspirala/matrix-engine/blob/master/lib/matrix-render.js" rel="nofollow noreferrer">FULL RENDER</a></p>

CC BY-SA 4.0
2024-12-31T02:57:25.143Z
Your question is too long; try to identify and reduce unnecessary details. I have two questions about your code: (1) why is `export const makeFBO2 = (gl, o)` but you call `makeFBO2` in the following way: `makeFBO2(object, world.GL.gl )`? (2) Can you make sure that when one of the `world.FBOS[fbindex].FB` is bound to the frame buffer, it's not simultaneously bound to a texture and got sampled (like here `world.GL.gl.bindTexture(world.GL.gl.TEXTURE_2D, object.FBO.FB.texture);`)?
Enigmatisms
CC BY-SA 4.0
2024-12-31T09:34:11.160Z
You are right - i will fix & update question i still have trouble...
Nikola Lukic
CC BY-SA 4.0
2024-12-31T11:44:10.720Z
@Enigmatisms I updated Q.  Only most importan code is here. Thnks for help!
Nikola Lukic
<glsl><webgl><javascript>
webGL Shadows implementation (FrameBuffer)
Nikola Lukic
# webGL Shadows implementation (FrameBuffer)

(Asked by: username_0 on 2024-12-30)

I wanna implement shadows example from [webgl2fundamentals](https://webgl2fundamentals.org/webgl/lessons/webgl-shadows.html)

also i a aware of framebuffer principe a have already working implementation of mirror projection.

Ignore VS extra vars .

I have trouble with shadows examples...

I always get black collor or error logs :

```json
GL_INVALID_OPERATION: Feedback loop formed between Framebuffer and active Texture.

```

My scene have two cubes. One `floor` and `myTextCube1` on top.

I added flag `object.shadows.FBO_IN_DRAW_PASS`.

**This is most important code from draw function:**
DRAWER:

```js
 ...

if(object.FBO && object.shadows.FBO_IN_DRAW_PASS == true) {
    // test FBO
    let textureMatrix = m4.identity();
    textureMatrix = m4.translate(textureMatrix, 0.5, 0.5, 0.5);
    textureMatrix = m4.scale(textureMatrix, 0.5, 0.5, 0.5);
    textureMatrix = m4.multiply(textureMatrix, 
                     object.shadows.lightProjectionMatrix);

    const lightWorldMatrix = m4.lookAt(
        [ object.shadows.lightPosition[0],
          object.shadows.lightPosition[1],
          object.shadows.lightPosition[2]
        ],
        [object.shadows.lightTarget[0] ,
         object.shadows.lightTarget[1] , 
         object.shadows.lightTarget[2]  
        ], // target
        [object.shadows.orientation[0], object.shadows.orientation[1], object.shadows.orientation[2]], // up
            );
    textureMatrix = m4.multiply(textureMatrix, 
              m4.inverse(lightWorldMatrix));
    const mat = m4.multiply(lightWorldMatrix, 
              m4.inverse(object.shadows.lightProjectionMatrix));
    // draw to the depth texture
    world.GL.gl.uniform1i(object.shaderProgram.u_projectedTexture, false, 0);
            world.GL.gl.uniformMatrix4fv(object.shaderProgram.u_textureMatrix, false, textureMatrix);
            world.GL.gl.uniform3fv(object.shaderProgram.lightWorldPositionLocation, object.shadows.lightPosition);
    
            world.GL.gl.uniformMatrix4fv(object.shaderProgram.u_world, false,
                m4.translate(object.position.worldLocation[0],
                    object.position.worldLocation[1],
                    object.position.worldLocation[2])
            );
            // world.GL.gl.uniformMatrix4fv(object.shaderProgram.u_world, false, mat);
            world.GL.gl.uniform3fv(object.shaderProgram.u_reverseLightDirection, lightWorldMatrix.slice(8, 11));
            world.GL.gl.uniform1f(object.shaderProgram.u_bias, object.shadows.bias);

            //  console.log('LOG FBO TEXT ACTIVATE')
            world.GL.gl.activeTexture(world.GL.gl.TEXTURE0);
            world.GL.gl.bindTexture(world.GL.gl.TEXTURE_2D, object.FBO.deepTexture);
            world.GL.gl.uniform1i(object.shaderProgram.u_projectedTexture, 0);

        } else {
      // console.log('normal tex')
            for(var t = 0;t < object.textures.length;t++) {
                if(object.custom.gl_texture == null) {
                    world.GL.gl.activeTexture(world.GL.gl['TEXTURE' + t]);
                    world.GL.gl.bindTexture(world.GL.gl.TEXTURE_2D, object.textures[t]);
                    world.GL.gl.pixelStorei(world.GL.gl.UNPACK_FLIP_Y_WEBGL, false);
                    if(object.texParams.MIPMAP == false) {
                        world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_S, object.texParams.TEXTURE_WRAP_S | world.GL.gl.REPEAT);
                        world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_T, object.texParams.TEXTURE_WRAP_T | world.GL.gl.REPEAT);
                        // -- Allocate storage for the texture
                        // world.GL.gl.texStorage2D(world.GL.gl.TEXTURE_2D, 1, world.GL.gl.RGB8, 512, 512);
                        // world.GL.gl.texSubImage2D(world.GL.gl.TEXTURE_2D, 0, 0, 0,512, 512, world.GL.gl.RGB, world.GL.gl.UNSIGNED_BYTE, object.textures[t]);
                    } else {
                        world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MAG_FILTER, object.texParams.TEXTURE_MAG_FILTER | world.GL.gl.LINEAR);
                        world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MIN_FILTER, object.texParams.TEXTURE_MIN_FILTER | world.GL.gl.LINEAR);
                        world.GL.gl.generateMipmap(world.GL.gl.TEXTURE_2D);
                    }

                    if(world.GL.extTFAnisotropic && object.texParams.ANISOTROPIC == true) {
                        world.GL.gl.texParameterf(world.GL.gl.TEXTURE_2D,
                            world.GL.extTFAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT,
                            world.GL.MAX_TEXTURE_MAX_ANISOTROPY_EXT);
                    }
                    world.GL.gl.uniform1i(object.shaderProgram.samplerUniform, t);
                    world.GL.gl.uniform1i(object.shaderProgram.u_projectedTexture, 0);
                } else {
                    object.custom.gl_texture(object, t);
                }
            }
        }
 ...
     

```

```js
export const makeFBO2 = (gl, o) => {
    if(typeof o === 'undefined') {
        var o = {width: 512,    height: 512};
    }
    var error = function() {console.log('Error in creating FBO!'); return null;}
    var gl = world.GL.gl;
    const depthTexture = gl.createTexture();
    const depthTextureSize = 512;
    gl.bindTexture(gl.TEXTURE_2D, depthTexture);
    gl.texImage2D(
        gl.TEXTURE_2D,      // target
        0,                  // mip level
        gl.DEPTH_COMPONENT32F, // internal format
        depthTextureSize,   // width
        depthTextureSize,   // height
        0,                  // border
        gl.DEPTH_COMPONENT, // format
        gl.FLOAT,           // type
        null);              // data
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

    const depthFramebuffer = gl.createFramebuffer();
    gl.bindFramebuffer(gl.FRAMEBUFFER, depthFramebuffer);
    gl.framebufferTexture2D(
        gl.FRAMEBUFFER,       // target
        gl.DEPTH_ATTACHMENT,  // attachment point
        gl.TEXTURE_2D,        // texture target
        depthTexture,         // texture
        0);                   // mip level

    return [depthFramebuffer, depthTexture];
}

```

And also importan part of code is render:
RENDER

```js

 
 
        world.GL.gl.bindFramebuffer(world.GL.gl.FRAMEBUFFER, world.FBOS[fbindex].FB);

        world.GL.gl.viewport(0, 0, 512, 512);
        world.GL.gl.clearColor(0.0, 1.0, 0.4, 1.0);
        world.GL.gl.clear(world.GL.gl.COLOR_BUFFER_BIT | world.GL.gl.DEPTH_BUFFER_BIT);
        world.GL.gl.enable(world.GL.gl.DEPTH_TEST);
        world.GL.gl.enable(world.GL.gl.CULL_FACE);
        world.GL.gl.disable(world.GL.gl.BLEND);

    // - draw all `non fbo` and `no blend`
    if(
                
                (world.contentList[looper].visible === true &&
                !world.contentList[looper].FBO &&
                world.contentList[looper].glBlend.blendEnabled == false) 
                 ||
                 (world.contentList[looper].visible === true &&
                    world.contentList[looper].shadows.FBO_IN_DRAW_PASS == false &&
                    world.contentList[looper].glBlend.blendEnabled == false)
            ) {

                    world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
                    world.drawCube(world.contentList[looper], 'noray');
                    world.contentList[looper].shadows.FBO_IN_DRAW_PASS = true;

}

    world.GL.gl.bindFramebuffer(world.GL.gl.FRAMEBUFFER, null);

    // All but no blend

        world.GL.gl.useProgram(world.contentList[looper].shaderProgram);
                world.contentList[looper].shadows.FBO_IN_DRAW_PASS = true;
                world.drawCube(world.contentList[looper]);
                world.animate(world.contentList[looper]);
                world.contentList[looper].shadows.FBO_IN_DRAW_PASS = false;

END OF REDER FUNC

App.operation.CameraPerspective = function() {
    this.GL.gl.viewport(0, 0, canvas.width, canvas.height);
    this.GL.gl.clear(this.GL.gl.COLOR_BUFFER_BIT | this.GL.gl.DEPTH_BUFFER_BIT);
    mat4.perspective(this.pMatrix, degToRad(App.camera.viewAngle), this.GL.gl.viewportWidth / this.GL.gl.viewportHeight, App.camera.nearViewpoint, App.camera.farViewpoint);
}

```

**And after all shaders part:**

```none
export function generateSpotLightShadowDefinitions() {
    return `// inject generateSpotLightShadowDefinitions
    uniform sampler2D u_projectedTexture;
    uniform sampler2D u_texture;
    in vec2 v_texcoord;
    uniform float u_bias;
    in vec4 v_projectedTexcoord;
    in vec3 v_surfaceToLight;
    in vec3 v_surfaceToView;
    uniform vec4 u_color;
    uniform float u_shininess;
    uniform vec3 u_lightDirection;
    uniform float u_innerLimit;
    uniform float u_outerLimit;
    uniform mat4 u_projection;
    uniform mat4 u_view;
    uniform mat4 u_world;
    uniform mat4 u_textureMatrix;
    uniform vec3 u_reverseLightDirection;
    `;
}

export function generateSpotLightShadowMain() {
    return `
    vec3 normal = normalize(v_normal);
    float light = dot(normal, u_reverseLightDirection);
    vec3 projectedTexcoord = v_projectedTexcoord.xyz / v_projectedTexcoord.w;
    float currentDepth = projectedTexcoord.z + u_bias;

    bool inRange =
            projectedTexcoord.x >= 0.0 &&
            projectedTexcoord.x <= 1.0 &&
            projectedTexcoord.y >= 0.0 &&
            projectedTexcoord.y <= 1.0;
    float projectedDepth = texture(u_projectedTexture, projectedTexcoord.xy).r;
    float shadowLight = (inRange && projectedDepth <= currentDepth) ? 0.0 : 1.0;
    vec4 texColor = texture(u_texture, v_texcoord) * vec4(1, 1, 1, 1);
    outColor = vec4(texColor.rgb * light * shadowLight , texColor.a);
    `;
}

```

VS GLSL:

```none
export function getInitVSCubeTexLight() {
  const f = `#version 300 es
  in vec3 aVertexPosition;
  in vec3 aVertexNormal;
  in vec2 aTextureCoord;
  uniform mat4 uMVMatrix;
  uniform mat4 uPMatrix;
  uniform mat3 uNMatrix;
  uniform vec3 uAmbientColor;
  uniform vec3 uLightingDirection;
  uniform vec3 uDirectionalColor;
  uniform bool uUseLighting;
  out vec2 vTextureCoord;
  out vec3 vLightWeighting;
  out vec3 meVertexPosition;
  uniform vec3 u_lightWorldPosition;
  out vec3 v_normal;
  out vec3 v_surfaceToLight;
  out vec3 v_surfaceToView;
  out mat4 uMVMatrixINTER;
  out mat3 uNMatrixINTER;
  out mat4 uPMatrixINNTER;
  in vec4 specularColor;
  out vec4 vColor;
  out vec3 vNormal;
  out vec4 vPosition;
  out float vDist;
  uniform mat4 u_textureMatrix;
  out vec2 v_texcoord;
  out vec4 v_projectedTexcoord;
  uniform mat4 u_world;

  void main(void) {
    meVertexPosition = aVertexPosition;
    uMVMatrixINTER = uMVMatrix;
    uNMatrixINTER = uNMatrix;
    uPMatrixINNTER = uPMatrix;
    vColor = specularColor;
    vNormal = normalize(mat3(u_world) * vec3(aVertexNormal)); 
    vPosition =  uMVMatrix * vec4(aVertexPosition, 1.0);
    vDist = gl_Position.w;
    v_normal = uNMatrix  *  vec3(aVertexNormal);
    vec3 surfaceWorldPosition = (uNMatrix * aVertexPosition).xyz;
    v_surfaceToLight = u_lightWorldPosition - surfaceWorldPosition;
    v_surfaceToView = (uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0)).xyz - surfaceWorldPosition;
    vec4 worldPosition =     vec4((uNMatrix * aVertexPosition).xyz, 1.0);
    v_texcoord = aTextureCoord;
   v_projectedTexcoord = u_textureMatrix * worldPosition;
    gl_Position   = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
    vTextureCoord = aTextureCoord;
    if (!uUseLighting) {
      vLightWeighting = vec3(1.0, 1.0, 1.0);
    } else {
      vec3 transformedNormal          = uNMatrix * aVertexNormal;
      float directionalLightWeighting = max(dot(transformedNormal, uLightingDirection), 0.0);
      vLightWeighting                 = uAmbientColor + uDirectionalColor * directionalLightWeighting;
    }
  }`;
    scriptManager.LOAD(f, "cubeLightTex-shader-vs", "x-shader/x-vertex", "shaders")
}

```

[![enter image description here](https://i.sstatic.net/OlSSgXx1.png)](https://i.sstatic.net/OlSSgXx1.png)

Any suggestion?
Looks like every cube for itself cast shadow no between cast...

If you wanna live demos of my library you can explore it [here](https://maximumroulette.com/apps/matrix-engine/examples-build.html).

UPDATE:

I found at <https://www.youtube.com/watch?v=0Xk96uN3Ceo&ab_channel=SketchpunkLabs>
on 24:00 minute

```
drawBuffers(gl.NONE)
readBuffer(gl.NONE)

```

I must try this lines...

Source code :
[github](https://github.com/zlatnaspirala/matrix-engine)

[FULL RENDER](https://github.com/zlatnaspirala/matrix-engine/blob/master/lib/matrix-render.js)

**Tags:** glsl, webgl, javascript

> **Comments:**
> **username_1**: Your question is too long; try to identify and reduce unnecessary details. I have two questions about your code: (1) why is `export const makeFBO2 = (gl, o)` but you call `makeFBO2` in the following way: `makeFBO2(object, world.GL.gl )`? (2) Can you make sure that when one of the `world.FBOS[fbindex].FB` is bound to the frame buffer, it's not simultaneously bound to a texture and got sampled (like here `world.GL.gl.bindTexture(world.GL.gl.TEXTURE_2D, object.FBO.FB.texture);`)?  
> **username_0**: You are right - i will fix & update question i still have trouble...  
> **username_0**: @username_1 I updated Q.  Only most importan code is here. Thnks for help!  

---

## 0 answers

