I wanna implement shadows example fromwebgl2fundamentals
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 :
GL_INVALID_OPERATION: Feedback loop formed between Framebuffer and active Texture.My scene have two cubes. Onefloor andmyTextCube1 on top.
I added flagobject.shadows.FBO_IN_DRAW_PASS.
This is most important code from draw function:DRAWER:
...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); } } } ...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
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 FUNCApp.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:
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:
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")}Any suggestion?Looks like every cube for itself cast shadow no between cast...
If you wanna live demos of my library you can explore ithere.
UPDATE:
I found athttps://www.youtube.com/watch?v=0Xk96uN3Ceo&ab_channel=SketchpunkLabson 24:00 minute
drawBuffers(gl.NONE)readBuffer(gl.NONE)I must try this lines...
Source code :github
- 1$\begingroup$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 callmakeFBO2in the following way:makeFBO2(object, world.GL.gl )? (2) Can you make sure that when one of theworld.FBOS[fbindex].FBis bound to the frame buffer, it's not simultaneously bound to a texture and got sampled (like hereworld.GL.gl.bindTexture(world.GL.gl.TEXTURE_2D, object.FBO.FB.texture);)?$\endgroup$2024-12-31 02:57:25 +00:00CommentedDec 31, 2024 at 2:57 - $\begingroup$You are right - i will fix & update question i still have trouble...$\endgroup$Nikola Lukic– Nikola Lukic2024-12-31 09:34:11 +00:00CommentedDec 31, 2024 at 9:34
- $\begingroup$@Enigmatisms I updated Q. Only most importan code is here. Thnks for help!$\endgroup$Nikola Lukic– Nikola Lukic2024-12-31 11:44:10 +00:00CommentedDec 31, 2024 at 11:44
