I am using the render to texture method for creating a multi shader program. And for various reasons. I need to first render a model to a texture with one shader program. Then render it again with a different shader program into a different texture. Then I have one final post processing shader that combines the results of the two. My problem is it seems that the second texture is overwriting the first texture. Is there a way to move textures? Or to render to a different texture without overwriting it. (Thanks for any help in advance!)
I have attached my code for reference:
// Basic rendering parameters
var mvMatrix = mat4.create(); // Model-view matrix for the main object
var pMatrix = mat4.create(); // Projection matrix
// Lighting control
var lightMatrix = mat4.create(); // Model-view matrix for the point light source
var lightPos = vec3.create(); // Camera-space position of the light source
var lightPower = 5.0; // "Power" of the light source
// Common parameters for shading models
var diffuseColor = [0.2392, 0.5216, 0.7765]; // Diffuse color
var specularColor = [1.0, 1.0, 1.0]; // Specular color
var ambientIntensity = 0.1; // Ambient
// Animation related variables
var rotY = 0.0; // object rotation
var rotY_light = 0.0; // light position rotation
//Set the shader variables from pMat (projection matrix) and
// from mMat which is the model and view transforms
function setUniforms(prog,pMat,mMat) {
gl.uniformMatrix4fv(prog.pMatrixUniform, false, pMat);
gl.uniformMatrix4fv(prog.mvMatrixUniform, false, mMat);
var nMatrix = mat4.transpose(mat4.inverse(mMat));
gl.uniformMatrix4fv(prog.nMatrixUniform, false, nMatrix);
gl.uniform3fv(prog.lightPosUniform, lightPos);
gl.uniform1f(prog.lightPowerUniform, lightPower);
gl.uniform3fv(prog.kdUniform, diffuseColor);
gl.uniform3fv(prog.ksUniform, specularColor);
gl.uniform1f(prog.ambientUniform, ambientIntensity);
}
function setLightPosition()
{
mat4.identity(lightMatrix);
mat4.translate(lightMatrix, [0.0, -1.0, -7.0]);
mat4.rotateX(lightMatrix, 0.3);
mat4.rotateY(lightMatrix, rotY_light);
lightPos.set([0.0, 2.5, 3.0]);
mat4.multiplyVec3(lightMatrix, lightPos);
}
var draw_edge = true;
var draw_light = false;
//will need to be updated to allow for multiple meshes
//Does the toon rendering of the scene to a texture so that we can post process on it
function renderSceneToTexture(shaderProg,mesh,color,depth,mMat,width,height)
{
var textOuput = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D,textOuput);
var format; var internalFormat;
if(color)
{
internalFormat= gl.RGBA;
format = gl.RGBA;
}
else
{
internalFormat= gl.LUMINANCE_ALPHA;
format = gl.LUMINANCE_ALPHA;
}
gl.texImage2D(gl.TEXTURE_2D,0,internalFormat,width,height,0,format,gl.UNSIGNED_BYTE,null);
//set out of bounds accesses to clamp and set sub pixel accesses to lerp
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);
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 fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER,fb);
//set frame buffer to first attacthment position
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D,textOuput,0);
var depthBuffer;
if(depth)
{
depthBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT,
gl.RENDERBUFFER, depthBuffer);
}
var pMat = mat4.create();
mat4.perspective(35, width/height, 0.1, 1000.0, pMat);
// Tell WebGL how to convert from clip space to pixels
gl.viewport(0, 0, width, height);
// Clear the attachment(s).
gl.clearColor(0.3, 0.3, 0.3, 1.0); // clear to black
gl.enable(gl.DEPTH_TEST);
gl.clear(gl.COLOR_BUFFER_BIT| gl.DEPTH_BUFFER_BIT);
gl.useProgram(shaderProg);
setUniforms(shaderProg,pMat,mMat);
gl.bindBuffer(gl.ARRAY_BUFFER, mesh.vertexBuffer);
gl.vertexAttribPointer(shaderProg.vertexPositionAttribute, mesh.vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, mesh.normalBuffer);
gl.vertexAttribPointer(shaderProg.vertexNormalAttribute, mesh.normalBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.indexBuffer);
gl.drawElements(gl.TRIANGLES, mesh.indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
if ( draw_light ) {
gl.useProgram(lightProgram);
gl.uniformMatrix4fv(lightProgram.pMatrixUniform, false, pMat);
gl.bindBuffer(gl.ARRAY_BUFFER, lightPositionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, Float32Array.from(lightPos), gl.DYNAMIC_DRAW);
gl.vertexAttribPointer(lightProgram.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.POINTS, 0, 1);
}
//should I unbind texture?
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.deleteFramebuffer(fb);
// render to the canvas
//gl.useProgram(null);
gl.bindTexture(gl.TEXTURE_2D,null);
return textOuput;
}
//mat4.copy was giving me errors, so I just copied the source code in here lol
function copy(out, a)
{
out[0] = a[0];
out[1] = a[1];
out[2] = a[2];
out[3] = a[3];
out[4] = a[4];
out[5] = a[5];
out[6] = a[6];
out[7] = a[7];
out[8] = a[8];
out[9] = a[9];
out[10] = a[10];
out[11] = a[11];
out[12] = a[12];
out[13] = a[13];
out[14] = a[14];
out[15] = a[15];
}
//Set the shader variables from pMat (projection matrix) and
// from mMat which is the model and view transforms
function setPostprocessingUniforms(prog,texture,normalTexture, width, height) {
gl.activeTexture(gl.TEXTURE0); //Do I need this?
gl.bindTexture(gl.TEXTURE_2D, texture); //and this?
gl.uniform1i(prog.uTextureUniform, texture);
gl.activeTexture(gl.TEXTURE1); //Do I need this?
gl.bindTexture(gl.TEXTURE_2D, normalTexture); //and this?
gl.uniform1i(prog.normImageTextureUniform, normalTexture);
gl.uniform2fv(prog.uTextureSizeUniform, [width,height]);
gl.uniform2fv(prog.uResolutionUniform, [width,height]);
}
function setRectangle(gl, x, y, width, height) {
var x1 = x;
var x2 = x + width;
var y1 = y;
var y2 = y + height;
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
x1, y1,
x2, y1,
x1, y2,
x1, y2,
x2, y1,
x2, y2,
]), gl.STATIC_DRAW);
}
function drawScene() {
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, [0.0, -1.0, -7.0]);
mat4.rotateX(mvMatrix, 0.3);
mat4.rotateY(mvMatrix, rotY);
mat4.multiply(mvMatrix, currentTransform);
var cpy = mat4.create();
copy(cpy,mvMatrix);
setLightPosition();
//consumes cpy matrix
//actual shader but writes to a texture
var normalsAsTexture = renderSceneToTexture(normalPassProgram,currentMesh,true,true,mvMatrix,gl.viewportWidth,gl.viewportHeight);
var sceneAsTexture = renderSceneToTexture(currentProgram,currentMesh,true,true,cpy,gl.viewportWidth,gl.viewportHeight);
// Create a buffer to put three 2d clip space points in
var positionBuffer = gl.createBuffer();
// Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer)
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
// Set a rectangle the same size as the image.
setRectangle(gl, 0, 0, gl.viewportWidth, gl.viewportHeight);
//screen is just 2 triangles, so we will post process on that
var texcoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
//bug is probably here and in set rectangle
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
0.0, 1.0,
1.0, 0.0,
1.0, 1.0,
]), gl.STATIC_DRAW);
//Post-process shader
gl.useProgram(postProcessProgram);
setPostprocessingUniforms(postProcessProgram,sceneAsTexture,normalsAsTexture, gl.viewportWidth, gl.viewportHeight);
//gl.activeTexture(texture);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
// Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER)
var size = 2; // 2 components per iteration
var type = gl.FLOAT; // the data is 32bit floats
var normalize = false; // don't normalize the data
var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position
var offset = 0; // start at the beginning of the buffer
gl.vertexAttribPointer(
postProcessProgram.vertexPositionAttribute, size, type, normalize, stride, offset);
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
gl.vertexAttribPointer(
postProcessProgram.texturePositionAttribute, size, type, normalize, stride, offset);
// Draw the rectangle.
var primitiveType = gl.TRIANGLES;
var offset = 0;
var count = 6;
gl.drawArrays(primitiveType, offset, count);
/*
setUniforms(postProcessProgram,pMatrix,mvMatrix);
gl.bindBuffer(gl.ARRAY_BUFFER, currentMesh.vertexBuffer);
gl.vertexAttribPointer(postProcessProgram.vertexPositionAttribute, currentMesh.vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, currentMesh.normalBuffer);
gl.vertexAttribPointer(postProcessProgram.vertexNormalAttribute, currentMesh.normalBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, currentMesh.indexBuffer);
gl.drawElements(gl.TRIANGLES, currentMesh.indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
*/
gl.bindTexture(gl.TEXTURE_2D,null);
gl.deleteTexture(sceneAsTexture);
gl.deleteTexture(normalsAsTexture);
}