I got it spot light.
I cut most interest part of code. it almost all there related with framebuffer:
App.operation.draws.drawSquareTex = function(object) {
var lighting = true;
// eslint-disable-next-line no-unused-vars
var localLooper = 0;
mat4.identity(object.mvMatrix);
this.mvPushMatrix(object.mvMatrix, this.mvMatrixStack);
if (object.isHUD === true) {
mat4.translate(object.mvMatrix, object.mvMatrix, object.position.worldLocation);
if(raycaster.checkingProcedureCalc) raycaster.checkingProcedureCalc(object);
} else {
if(App.camera.FirstPersonController == true) {
camera.setCamera(object);
} else if(App.camera.SceneController == true) {
camera.setSceneCamera(object);
}
mat4.translate(object.mvMatrix, object.mvMatrix, object.position.worldLocation);
if(raycaster.checkingProcedureCalc) raycaster.checkingProcedureCalc(object);
mat4.rotate(object.mvMatrix, object.mvMatrix, degToRad(object.rotation.rz), object.rotation.getRotDirZ());
mat4.rotate(object.mvMatrix, object.mvMatrix, degToRad(object.rotation.rx), object.rotation.getRotDirX());
mat4.rotate(object.mvMatrix, object.mvMatrix, degToRad(object.rotation.ry), object.rotation.getRotDirY());
}
// V
if(object.vertexPositionBuffer) {
world.GL.gl.bindBuffer(world.GL.gl.ARRAY_BUFFER, object.vertexPositionBuffer);
if(object.geometry.dynamicBuffer == true) {
world.GL.gl.bufferData(world.GL.gl.ARRAY_BUFFER, object.geometry.vertices, world.GL.gl.STATIC_DRAW);
}
world.GL.gl.vertexAttribPointer(object.shaderProgram.vertexPositionAttribute, object.vertexPositionBuffer.itemSize, world.GL.gl.FLOAT, false, 0, 0);
world.GL.gl.enableVertexAttribArray(object.shaderProgram.vertexPositionAttribute);
localLooper = localLooper + 1;
}
// C
if(object.vertexColorBuffer) {
world.GL.gl.bindBuffer(world.GL.gl.ARRAY_BUFFER, object.vertexColorBuffer);
world.GL.gl.vertexAttribPointer(object.shaderProgram.vertexColorAttribute, object.vertexColorBuffer.itemSize, world.GL.gl.FLOAT, false, 0, 0);
world.GL.gl.enableVertexAttribArray(object.shaderProgram.vertexColorAttribute);
localLooper = localLooper + 1;
}
// L
if(lighting && object.shaderProgram.useLightingUniform) {
world.GL.gl.uniform1i(object.shaderProgram.useLightingUniform, lighting);
/* Set the normals */
if(object.vertexNormalBuffer) {
world.GL.gl.bindBuffer(world.GL.gl.ARRAY_BUFFER, object.vertexNormalBuffer);
world.GL.gl.vertexAttribPointer(object.shaderProgram.vertexNormalAttribute, object.vertexNormalBuffer.itemSize, world.GL.gl.FLOAT, false, 0, 0);
world.GL.gl.enableVertexAttribArray(object.shaderProgram.vertexNormalAttribute);
localLooper = localLooper + 1;
}
/* Ambient light - posible deplaced */
if(object.shaderProgram.ambientColorUniform) {
if(E('ambLight') && E('ambLight').color) {
world.GL.gl.uniform3f(object.shaderProgram.ambientColorUniform, parseFloat(E('ambLight').color.rgb[0]), parseFloat(E('ambLight').color.rgb[1]), parseFloat(E('ambLight').color.rgb[2]));
} else {
world.GL.gl.uniform3f(object.shaderProgram.ambientColorUniform, object.LightsData.ambientLight.r, object.LightsData.ambientLight.g, object.LightsData.ambientLight.b);
}
}
/* Directional light */
if(object.shaderProgram.directionalColorUniform) {
if(E('dirLight') && E('dirLight').color) {
world.GL.gl.uniform3f(object.shaderProgram.directionalColorUniform, parseFloat(E('dirLight').color.rgb[0]), parseFloat(E('dirLight').color.rgb[1]), parseFloat(E('dirLight').color.rgb[2]));
} else {
world.GL.gl.uniform3f(object.shaderProgram.directionalColorUniform, object.LightsData.directionLight.R(), object.LightsData.directionLight.G(), object.LightsData.directionLight.B());
}
}
/* Normalize the direction */
var lightingDirection = null;
if(object.shaderProgram.lightingDirectionUniform) {
if(E('dirX') && E('dirY') && E('dirZ')) {
lightingDirection = [parseFloat(E('dirX').value), parseFloat(E('dirY').value), parseFloat(E('dirZ').value)];
} else {
lightingDirection = [object.LightsData.lightingDirection.r, object.LightsData.lightingDirection.g, object.LightsData.lightingDirection.b];
}
var adjustedLD = vec3.create();
vec3.normalize(adjustedLD, lightingDirection);
vec3.scale(adjustedLD, adjustedLD, -1);
world.GL.gl.uniform3fv(object.shaderProgram.lightingDirectionUniform, adjustedLD);
}
} else {
if(object.shaderProgram.useLightingUniform) {
if(object.shaderProgram.ambientColorUniform) {
world.GL.gl.uniform3f(object.shaderProgram.ambientColorUniform, parseFloat(1), parseFloat(2), parseFloat(0));
}
if(object.shaderProgram.directionalColorUniform) {
world.GL.gl.uniform3f(object.shaderProgram.directionalColorUniform, parseFloat(1), parseFloat(0), parseFloat(0));
}
}
}
// T
if(object.vertexTexCoordBuffer) {
world.GL.gl.bindBuffer(world.GL.gl.ARRAY_BUFFER, object.vertexTexCoordBuffer);
if(object.geometry.dynamicBuffer == true) {
world.GL.gl.bufferData(world.GL.gl.ARRAY_BUFFER, object.geometry.texCoords, world.GL.gl.STATIC_DRAW);
}
world.GL.gl.vertexAttribPointer(object.shaderProgram.textureCoordAttribute, object.vertexTexCoordBuffer.itemSize, world.GL.gl.FLOAT, false, 0, 0);
world.GL.gl.enableVertexAttribArray(object.shaderProgram.textureCoordAttribute);
if(object.streamTextures != null) {
// video/webcam tex
// App.tools.loadVideoTexture('glVideoTexture', object.streamTextures.videoImage);
App.tools.loadVideoTexture('glVideoTexture', object.streamTextures.video);
world.GL.gl.uniform1i(object.shaderProgram.samplerUniform, 0);
} else {
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);
world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MAG_FILTER, world.GL.gl.NEAREST);
world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MIN_FILTER, world.GL.gl.NEAREST);
world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_S, world.GL.gl.CLAMP_TO_EDGE);
world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_T, world.GL.gl.CLAMP_TO_EDGE);
// -- 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, world.GL.gl.RGB, world.GL.gl.UNSIGNED_BYTE, image);
//world.GL.gl.generateMipmap(world.GL.gl.TEXTURE_2D);
// ori world.GL.gl.uniform1i(object.shaderProgram.samplerUniform, t);
// var nothing =
// world.GL.gl.uniform1i(object.shaderProgram['samplerUniform' + t], t);
world.GL.gl.uniform1i(object.shaderProgram.samplerUniform, t);
} else {
object.custom.gl_texture(object, t);
}
}
}
localLooper = localLooper + 1;
}
world.GL.gl.bindBuffer(world.GL.gl.ELEMENT_ARRAY_BUFFER, object.vertexIndexBuffer);
world.setMatrixUniforms(object, this.pMatrix, object.mvMatrix);
if(object.vertexNormalBuffer && object.shaderProgram.nMatrixUniform) {
var normalMatrix = mat3.create();
mat3.normalFromMat4(normalMatrix, object.mvMatrix);
mat3.transpose(normalMatrix, normalMatrix);
world.GL.gl.uniformMatrix3fv(object.shaderProgram.nMatrixUniform, false, normalMatrix);
}
// world.disableUnusedAttr( world.GL.gl, localLooper);
world.disableUnusedAttr(world.GL.gl, 4);
if(object.glBlend.blendEnabled == true) {
if(!world.GL.gl.isEnabled(world.GL.gl.BLEND)) {
// world.GL.gl.disable(world.GL.gl.DEPTH_TEST);
world.GL.gl.enable(world.GL.gl.BLEND);
}
try {
world.GL.gl.blendFunc(world.GL.gl[object.glBlend.blendParamSrc], world.GL.gl[object.glBlend.blendParamDest]);
} catch(e) {
console.log(e);
}
} else {
world.GL.gl.disable(world.GL.gl.BLEND);
world.GL.gl.enable(world.GL.gl.DEPTH_TEST);
world.GL.gl.enable(world.GL.gl.CULL_FACE);
}
// shadows
if(object.shadows && object.shadows.type == 'spot' ||
object.shadows.type == 'spot-shadow') {
const settings = {
cameraX: 6,
cameraY: 5,
posX: 2.5,
posY: 4.8,
posZ: 4.3,
targetX: 2.5,
targetY: 0,
targetZ: 3.5,
projWidth: 1,
projHeight: 1,
perspective: true,
fieldOfView: 120,
bias: -0.006,
};
if (!object.shadows.depthFramebuffer) {
console.log('ONLY ONCE !!!')
var depthFramebuffer = depthTextures(world.GL.gl);
object.shadows.depthFramebuffer = depthFramebuffer[0];
object.shadows.TEST = depthFramebuffer[1];
}
// console.log(" SHADOWS -> " , object.shadows)
// set the light position
world.GL.gl.uniform3fv(object.shaderProgram.lightWorldPositionLocation, object.shadows.lightPosition);
// set the camera/view position
// gl.uniform3fv(object.shaderProgram.viewWorldPositionLocation, camera);
// world.GL.gl.uniform3fv(object.shaderProgram.viewWorldPositionLocation, [matrixEngine.Events.camera.xPos, matrixEngine.Events.camera.yPos, matrixEngine.Events.camera.zPos]);
world.GL.gl.uniform3fv(object.shaderProgram.viewWorldPositionLocation, object.shadows.lightPosition);
// Set the shininess
world.GL.gl.uniform1f(object.shaderProgram.shininessLocation, object.shadows.shininess);
// Set the spotlight uniforms
{
var target = [0, 0, 0]; // object.position.worldLocation;
var up = [0, 1, 0];
var lmat = m4.lookAt(object.shadows.lightPosition, target, up);
// var lmat = m4.lookAt(object.position.worldLocation, target, up);
lmat = m4.multiply(m4.xRotation(object.shadows.lightRotationX), lmat);
lmat = m4.multiply(m4.yRotation(object.shadows.lightRotationY), lmat);
// get the zAxis from the matrix
// negate it because lookAt looks down the -Z axis
object.shadows.lightDirection = [-lmat[8], -lmat[9], -lmat[10]];
// object.shadows.lightDirection = [-0, -0, -1];
}
// test
const viewMatrix = m4.inverse(lmat);
// first draw from the POV of the light
const lightWorldMatrix = m4.lookAt(
[settings.posX, settings.posY, settings.posZ], // position
[settings.targetX, settings.targetY, settings.targetZ], // target
[0, 1, 0], // up
);
const lightProjectionMatrix = settings.perspective
? m4.perspective(
degToRad(settings.fieldOfView),
settings.projWidth / settings.projHeight,
0.5, // near
10) // far
: m4.orthographic(
-settings.projWidth / 2, // left
settings.projWidth / 2, // right
-settings.projHeight / 2, // bottom
settings.projHeight / 2, // top
0.5, // near
10); // far
// draw to the depth texture
world.GL.gl.bindFramebuffer(world.GL.gl.FRAMEBUFFER, object.shadows.depthFramebuffer);
world.GL.gl.viewport(0, 0, 512, 512);
world.GL.gl.clear( world.GL.gl.COLOR_BUFFER_BIT | world.GL.gl.DEPTH_BUFFER_BIT);
// draw
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, lightProjectionMatrix);
// use the inverse of this world matrix to make
// a matrix that will transform other positions
// to be relative this world space.
textureMatrix = m4.multiply(
textureMatrix,
m4.inverse(lightWorldMatrix));
world.GL.gl.uniform4fv(object.shaderProgram.u_textureMatrix, textureMatrix);
world.GL.gl.uniform3fv(object.shaderProgram.lightDirectionLocation, object.shadows.lightDirection);
world.GL.gl.uniform1f(object.shaderProgram.innerLimitLocation, Math.cos(object.shadows.innerLimit));
world.GL.gl.uniform1f(object.shaderProgram.outerLimitLocation, Math.cos(object.shadows.outerLimit));
// TEST
world.GL.gl.drawElements(world.GL.gl[object.glDrawElements.mode], object.glDrawElements.numberOfIndicesRender, world.GL.gl.UNSIGNED_SHORT, 0);
world.GL.gl.bindFramebuffer(world.GL.gl.FRAMEBUFFER, null);
world.GL.gl.viewport(0, 0, world.GL.gl.canvas.width, world.GL.gl.canvas.height);
world.GL.gl.clearColor(1, 1, 1, 1);
world.GL.gl.clear(world.GL.gl.COLOR_BUFFER_BIT | world.GL.gl.DEPTH_BUFFER_BIT);
// REPEAT NORMAL TEX
world.GL.gl.activeTexture(world.GL.gl['TEXTURE' + 0]);
world.GL.gl.bindTexture(world.GL.gl.TEXTURE_2D, object.shadows.TEST);
// world.GL.gl.pixelStorei(world.GL.gl.UNPACK_FLIP_Y_WEBGL, false);
// world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MAG_FILTER, world.GL.gl.NEAREST);
// world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MIN_FILTER, world.GL.gl.NEAREST);
// world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_S, world.GL.gl.CLAMP_TO_EDGE);
// world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_T, world.GL.gl.CLAMP_TO_EDGE);
// world.GL.gl.uniform1i(object.shaderProgram.samplerUniform, t);
}
world.GL.gl.drawElements(world.GL.gl[object.glDrawElements.mode], object.glDrawElements.numberOfIndicesRender, world.GL.gl.UNSIGNED_SHORT, 0);
object.instancedDraws.overrideDrawArraysInstance(object);
this.mvPopMatrix(object.mvMatrix, this.mvMatrixStack);
};
250x GL_INVALID_OPERATION: Feedback loop formed between Framebuffer and active Texture.
1x GL_INVALID_OPERATION: Feedback loop formed between Framebuffer and active Texture.
Shaders must be #version 300 es
or i can keep it on ver 2 ?
Any suggestion ?
Feedback loop formed between Framebuffer and active Texture.
You cannot render to a texture that is also used as a source in the fragment shader. This is a feedback loop. You will need 2 textures. One that you read from and one that you render into. Switch this to textures before each frame (ping-pong shading).