Reputation: 11
I have set up two shaders in my program to use for different objects in the code. The shaders individually have been tested and work, so the issue lies with the webgl code. Here's what I have in the initial shading code.
var vertexShader = this.getShader("VertexShader2");
this.shaderProgram = gl.createProgram();
gl.attachShader(this.shaderProgram, vertexShader);
gl.attachShader(this.shaderProgram, fragmentShader);
gl.linkProgram(this.shaderProgram);
if(!gl.getProgramParameter(this.shaderProgram, gl.LINK_STATUS)){
console.log("unable to init shader program");
}
gl.useProgram(GC.canvas.shaderProgram);
GC.vertexPositionAttribute = gl.getAttribLocation(this.shaderProgram, "vPos");
gl.enableVertexAttribArray(GC.vertexPositionAttribute);
GC.barycentricAttribute = gl.getAttribLocation(this.shaderProgram, "bary");
gl.enableVertexAttribArray(GC.barycentricAttribute);
GC.normalAttribute = gl.getAttribLocation(this.shaderProgram, "norm");
gl.enableVertexAttribArray(GC.normalAttribute);
var fragmentShader2 = this.getShader("FragmentShader1");
var vertexShader2 = this.getShader("VertexShader1");
this.shaderProgram2 = gl.createProgram();
gl.attachShader(this.shaderProgram2, vertexShader2);
gl.attachShader(this.shaderProgram2, fragmentShader2);
gl.linkProgram(this.shaderProgram2);
if(!gl.getProgramParameter(this.shaderProgram2, gl.LINK_STATUS)){
console.log("unable to init shader program 2");
}
GC.shaderProgram = this.shaderProgram;
GC.shaderProgram2 = this.shaderProgram2;
And in a separate function to initialize the shaders...
gl.useProgram(GC.canvas.shaderProgram2);
GC.vertexPositionAttribute2 = gl.getAttribLocation(GC.shaderProgram2, "vPos");
gl.enableVertexAttribArray(GC.vertexPositionAttribute2);
GC.barycentricAttribute2 = gl.getAttribLocation(GC.shaderProgram2, "bary");
gl.enableVertexAttribArray(GC.barycentricAttribute2);
GC.textureCoordAttribute = gl.getAttribLocation(GC.shaderProgram2, "aTextureCoord");
gl.enableVertexAttribArray(GC.textureCoordAttribute);
GC.vert_tangPtr = gl.getAttribLocation(GC.shaderProgram2, "vert_tang");
gl.enableVertexAttribArray(GC.vert_tangPtr);
GC.vert_bitangPtr = gl.getAttribLocation(GC.shaderProgram2, "vert_bitang");
gl.enableVertexAttribArray(GC.vert_bitangPtr);
GC.vert_uvPtr = gl.getAttribLocation(GC.shaderProgram2, "vert_uv");
gl.enableVertexAttribArray(GC.vert_uvPtr);
}
And the webgl code later to switch the shader and set up the object.
gl.useProgram(GC.shaderProgram2);
setupShader2();
mvTranslate([(m1.minX+m1.maxX)/2.0,(m1.minY+m1.maxY)/2.0,(m1.minZ+m1.maxZ)/2.0],GC);
mvMultMatrix(camera.Transform,GC);//multiply by the transformation
//translate back to original origin
mvTranslate([-(m1.minX+m1.maxX)/2.0,-(m1.minY+m1.maxY)/2.0,-(m1.minZ+m1.maxZ)/2.0],GC);
//---------
//passes modelview and projection matrices to the vertex shader
setMatrixUniforms(GC);
GC.norm_mtx = GC.mvMatrix;
GC.norm_mtx = GC.norm_mtx.inverse();
GC.norm_mtx = GC.norm_mtx.transpose();
var pnormal = gl.getUniformLocation(GC.shaderProgram2, "norm_mtx");
gl.uniformMatrix4fv(pnormal, false, new Float32Array(GC.norm_mtx.flatten()));
//pass the vertex buffer to the shader
gl.bindBuffer(gl.ARRAY_BUFFER, m1.vertexBuffer);
gl.vertexAttribPointer(GC.vertexPositionAttribute2, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(GC.vertexPositionAttribute2);
//pass the barycentric coords to the shader for edge detection
gl.bindBuffer(gl.ARRAY_BUFFER, GC.barycentricBuffer);
gl.vertexAttribPointer(GC.barycentricAttribute2, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(GC.barycentricAttribute2);
gl.bindBuffer(gl.ARRAY_BUFFER, GC.textureCoordBuffer);
gl.vertexAttribPointer(GC.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(GC.vtextureCoordAttribute);
gl.bindBuffer(gl.ARRAY_BUFFER, GC.vert_tang);
gl.vertexAttribPointer(GC.vert_tangPtr, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, GC.vert_bitang);
gl.vertexAttribPointer(GC.vert_bitangPtr, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, GC.vert_uv);
gl.vertexAttribPointer(GC.vert_uvPtr, 2, gl.FLOAT, false, 0, 0);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, GC.tex_norm);
var uni = gl.getUniformLocation(GC.shaderProgram2, "tex_norm");
gl.uniform1i(uni, 0);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, GC.tex_diffuse);
uni = gl.getUniformLocation(GC.shaderProgram2, "tex_diffuse");
gl.uniform1i(uni, 1);
gl.activeTexture(gl.TEXTURE2);
gl.bindTexture(gl.TEXTURE_2D, GC.tex_depth);
uni = gl.getUniformLocation(GC.shaderProgram2, "tex_depth");
gl.uniform1i(uni, 2);
gl.uniform1i(GC.uSampler, 0);
var scale = 0.01 * 1.0;
uni = gl.getUniformLocation(GC.shaderProgram2, "depth_scale");
gl.uniform1f(uni, scale);
var steps = 1.0;
uni = gl.getUniformLocation(GC.shaderProgram2, "num_layers");
gl.uniform1f(uni, steps);
var show_tex = true;
uni = gl. getUniformLocation(GC.shaderProgram2, "show_tex");
gl.uniform1i(uni, show_tex);
//draw everything
gl.drawArrays(gl.TRIANGLES,0,m1.indices.length);
Please take a look and help-it's currently not showing any object past the first.
Upvotes: 1
Views: 84
Reputation: 464
In the code you shared, I see different things missing. You link a program and use another one to get vertex attributes locations
gl.linkProgram(this.shaderProgram);
// ...
gl.useProgram(GC.canvas.shaderProgram);
You get the vertex attributes for the second program in your separate function, but we don't know when it's called. I think it would have been easier to read and understand if you had created 2 functions to initialize each program
function setProgram()
{
fragmentShader = this.getShader("VertexShader2");
vertexShader = this.getShader("VertexShader2");
this.shaderProgram = gl.createProgram();
gl.attachShader(this.shaderProgram, vertexShader);
gl.attachShader(this.shaderProgram, fragmentShader);
gl.linkProgram(this.shaderProgram);
if(!gl.getProgramParameter(this.shaderProgram, gl.LINK_STATUS)){
console.log("unable to init shader program");
}
gl.useProgram(this.shaderProgram);
GC.vertexPositionAttribute = gl.getAttribLocation(this.shaderProgram, "vPos");
gl.enableVertexAttribArray(GC.vertexPositionAttribute);
GC.barycentricAttribute = gl.getAttribLocation(this.shaderProgram, "bary");
gl.enableVertexAttribArray(GC.barycentricAttribute);
GC.normalAttribute = gl.getAttribLocation(this.shaderProgram, "norm");
gl.enableVertexAttribArray(GC.normalAttribute);
GC.shaderProgram = this.shaderProgram;
}
function setProgram2()
{
var fragmentShader2 = this.getShader("FragmentShader1");
var vertexShader2 = this.getShader("VertexShader1");
this.shaderProgram2 = gl.createProgram();
gl.attachShader(this.shaderProgram2, vertexShader2);
gl.attachShader(this.shaderProgram2, fragmentShader2);
gl.linkProgram(this.shaderProgram2);
if(!gl.getProgramParameter(this.shaderProgram2, gl.LINK_STATUS)){
console.log("unable to init shader program 2");
}
gl.useProgram(this.shaderProgram2);
GC.vertexPositionAttribute2 = gl.getAttribLocation(GC.shaderProgram2, "vPos");
gl.enableVertexAttribArray(GC.vertexPositionAttribute2);
GC.barycentricAttribute2 = gl.getAttribLocation(GC.shaderProgram2, "bary");
gl.enableVertexAttribArray(GC.barycentricAttribute2);
GC.textureCoordAttribute = gl.getAttribLocation(GC.shaderProgram2, "aTextureCoord");
gl.enableVertexAttribArray(GC.textureCoordAttribute);
GC.vert_tangPtr = gl.getAttribLocation(GC.shaderProgram2, "vert_tang");
gl.enableVertexAttribArray(GC.vert_tangPtr);
GC.vert_bitangPtr = gl.getAttribLocation(GC.shaderProgram2, "vert_bitang");
gl.enableVertexAttribArray(GC.vert_bitangPtr);
GC.vert_uvPtr = gl.getAttribLocation(GC.shaderProgram2, "vert_uv");
gl.enableVertexAttribArray(GC.vert_uvPtr);
GC.shaderProgram2 = this.shaderProgram2;
}
And I don't see where you use the second program in the animation loop.
Remember WebGL is kind of a state machine. Everything that is set up when you call draw function is used. You can split the code in 2 parts: what should be executed at init time and once the animation loop is running.
At init time You need to setup your objects geometry and create the programs
function init()
{
// for each buffer, create, bind and set data
gl.createBuffer(...)
gl.bindBuffer(gl.ARRAY_BUFFER, ...)
gl.bufferData(...)
// Do the same with every buffer
// for each program, create, compile and validate shaders, create the program, attach shaders, link and validate
var program = createProgram()
// Use the program
gl.useProgram(program)
// Get vertex attribute locations
gl.getAttribLocation(...)
// Get uniform locations
gl.getUniformLocation(...)
// Do the same with every program
}
In the animation loop, you need to set the current state before drawing each mesh in a same frame:
If something is missing, it will be used from the previous state. That can explain why you don't see your objects.
function renderObject()
{
// State requirements (if needed)
gl.enable(...)
gl.disable(...)
// Bind textures
gl.bindTexture(gl.TEXTURE_2D, ...) // repeat this for each texture your program needs
// Using program
gl.useProgram(program) // this enable the program you need for the draw
// Bind buffers
gl.bindBuffer(gl.ARRAY_BUFFER, ...) // repeat this for each buffer your program needs
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ...)
// Specify attributes layout (use stored locations)
gl.vertexAttribPointer(...)
// Enable vertex attributes
gl.enableVertexAttribArray(...)
// Set uniform values (use stored locations)
gl.uniform1234fv(...)
// And finally draw your mesh
gl.drawArrays(...)
// Clear what you won't need anymore (bind things to null, disable...)
gl.disableVertexAttribArray(...)
}
Upvotes: 1