I have a problem with a program written in webgl and I don't know how to debug it because the browser console shows no errors. Webgl is drawing nothing at all.
I have the following set of shaders:
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
uniform sampler2D uSampler;
varying vec2 vTextureCoord;
varying vec3 vEye;
varying vec3 vNormal;
uniform vec3 uLightDirection; // Vector direccion de la luz
uniform vec3 uDirectionalColor; // Color de la luz direcional
uniform vec3 uColShadeless;
uniform vec3 uAmbientColor;
uniform float uKAmbiente;
uniform vec3 uColDifuso;
uniform float uKDifuso;
uniform vec3 uColEspecular;
uniform float uKEspecular;
uniform float uGlossiness;
void main(void)
{
vec3 normal = normalize(vNormal);
float mLambert = max(dot(normal, uLightDirection), 0.0);
vec3 vLuzLambert = uDirectionalColor * mLambert;
vec3 r = 2.0 * max(dot(normal, uLightDirection), 0.0) * normal - uLightDirection;
//vec3 r = reflect(uLightDirection, normal); // <- Da glossines del otro lado también
float specular = pow(max(dot(r, normalize(vEye)), 0.0), uGlossiness) ;
vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
vec3 componenteShadeless = uColShadeless * textureColor.rgb * uColDifuso; // luz autoiluminada * colores difusos
vec3 componenteAmbiente = uKAmbiente * uAmbientColor * textureColor.rgb * uColDifuso; // k% * luz ambiente * colores difusos
vec3 componenteDifusa = uKDifuso * textureColor.rgb * uColDifuso * vLuzLambert;
vec3 componenteEspecular = uKEspecular * specular * uColEspecular ;
gl_FragColor = vec4(componenteShadeless + componenteAmbiente + componenteDifusa + componenteEspecular, textureColor.a);
}
</script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aTextureCoord;
uniform mat4 uViewMatrix;
uniform mat4 uModelMatrix;
uniform mat4 uPMatrix;
uniform mat3 uNMatrix;
varying vec2 vTextureCoord;
varying vec3 vEye;
varying vec3 vNormal;
uniform vec2 aUVOffset;
void main(void)
{
// Transformamos al vértice al espacio de la cámara
vec4 pos_camera_view = uViewMatrix * uModelMatrix * vec4(aVertexPosition, 1.0);
// Transformamos al vértice al espacio de la proyección
gl_Position = uPMatrix * pos_camera_view;
// Coordenada de textura
vTextureCoord.x = aTextureCoord.x + aUVOffset.x;
vTextureCoord.y = aTextureCoord.y + aUVOffset.y;
// Para iluminación
vEye = -vec3(pos_camera_view.xyz);
vNormal = uNMatrix * aVertexNormal;
}
</script>
<script id="vs" type="x-shader/x-vertex">
attribute vec3 aPositionL;
attribute vec3 aNormalL;
attribute vec3 aTangentL;
attribute vec2 aTexCoord;
uniform mat4 uMatrixMVP;
uniform mat4 uMatrixMV;
varying vec4 vPositionV;
varying vec3 vNormalV;
varying vec3 vTangentV;
varying vec2 vTexCoord;
attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aTextureCoord;
uniform mat4 uViewMatrix;
uniform mat4 uModelMatrix;
uniform mat4 uPMatrix;
uniform mat3 uNMatrix;
varying vec3 vNormal;
uniform vec2 aUVOffset;
void main(void)
{
// Transformamos al vértice al espacio de la cámara
vec4 pos_camera_view = uViewMatrix * uModelMatrix * vec4(aPositionL, 1.0);
// Transformamos al vértice al espacio de la proyección
gl_Position = uPMatrix * pos_camera_view;
vNormal = uNMatrix * aVertexNormal;
vPositionV = uMatrixMV * vec4(aPositionL, 1.0);
vNormalV = (uMatrixMV * vec4(aNormalL, 0.0)).xyz;
vTangentV = (uMatrixMV * vec4(aTangentL, 0.0)).xyz;
vTexCoord = aTexCoord;
}
</script>
<script id="fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision highp float;
#endif
uniform sampler2D uColorSampler;
uniform sampler2D uNormalSampler;
uniform float uTime;
varying vec4 vPositionV;
varying vec3 vNormalV;
varying vec3 vTangentV;
varying vec2 vTexCoord;
void main(void) {
vec3 diffuse = texture2D(uColorSampler, vTexCoord).rgb;
vec3 normalT = texture2D(uNormalSampler, vTexCoord).xyz;
normalT.y = 1.0 - normalT.y;
normalT = 2.0 * normalT - vec3(1.0, 1.0, 1.0);
normalT.z *= 10.0;
vec3 binormalV = cross(vNormalV, vTangentV);
vec3 normalV = normalT.x * vTangentV + normalT.y * binormalV + normalT.z * vNormalV;
normalV = normalize(normalV);
vec3 lightV = normalize(vec3(10.0 * cos(uTime), 10.0, 10.0 * sin(uTime)));
float d = dot(normalV, lightV);
float s = dot(reflect(-lightV, normalV), normalize(-vPositionV.xyz));
s = pow(s, 30.0);
vec3 color = diffuse * (0.1 + 0.5 * d + 0.4 * s);
gl_FragColor = vec4(color, 1.0);
}
So vs and fs are shaders used to draw a surface with a normal map texture. I use shader-fs and shader-vs for the rest of the code.
The following code is used to init shaders and change them:
function initShaders()
{
var fragmentShader = getShader(gl, "shader-fs");
var vertexShader = getShader(gl, "shader-vs");
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
initShaders2();
}
function changeShaderBasic()
{
gl.useProgram(shaderProgramMap);
gl.disableVertexAttribArray(shaderProgramMap.aPositionL);
gl.disableVertexAttribArray(shaderProgramMap.aNormalL);
gl.disableVertexAttribArray(shaderProgramMap.aTangentL);
gl.disableVertexAttribArray(shaderProgramMap.aTexCoord);
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
shaderProgram.vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal");
gl.enableVertexAttribArray(shaderProgram.vertexNormalAttribute);
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.ViewMatrixUniform = gl.getUniformLocation(shaderProgram, "uViewMatrix");
shaderProgram.ModelMatrixUniform = gl.getUniformLocation(shaderProgram, "uModelMatrix");
shaderProgram.nMatrixUniform = gl.getUniformLocation(shaderProgram, "uNMatrix");
shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
shaderProgram.ambientColorUniform = gl.getUniformLocation(shaderProgram, "uAmbientColor"); // Color ambiente
shaderProgram.lightingDirectionUniform = gl.getUniformLocation(shaderProgram, "uLightDirection"); // Direccion de la luz
shaderProgram.directionalColorUniform = gl.getUniformLocation(shaderProgram, "uDirectionalColor"); // Color de la luz
shaderProgram.shadelessColorUniform = gl.getUniformLocation(shaderProgram, "uColShadeless");
shaderProgram.ambientKUniform = gl.getUniformLocation(shaderProgram, "uKAmbiente");
shaderProgram.diffuseColorUniform = gl.getUniformLocation(shaderProgram, "uColDifuso");
shaderProgram.diffuseKUniform = gl.getUniformLocation(shaderProgram, "uKDifuso");
shaderProgram.specularColorUniform = gl.getUniformLocation(shaderProgram, "uColEspecular");
shaderProgram.specularKUniform = gl.getUniformLocation(shaderProgram, "uKEspecular");
shaderProgram.specularGlossiness = gl.getUniformLocation(shaderProgram, "uGlossiness");
shaderProgram.uvOffsetUniform = gl.getUniformLocation(shaderProgram, "aUVOffset");
}
function initShaders2() {
var vs = getShader(gl,'vs');
var fs = getShader(gl,'fs');
shaderProgramMap = gl.createProgram();
gl.attachShader(shaderProgramMap, vs);
gl.attachShader(shaderProgramMap, fs);
gl.linkProgram(shaderProgramMap);
if (!gl.getProgramParameter(shaderProgramMap, gl.LINK_STATUS)) {
alert('Could not link the shader normal program.');
return;
}
}
function changeShaderNormal()
{
gl.useProgram(shaderProgram);
gl.disableVertexAttribArray(shaderProgram.vertexPositionAttribute);
gl.disableVertexAttribArray(shaderProgram.textureCoordAttribute);
gl.disableVertexAttribArray(shaderProgram.vertexNormalAttribute);
gl.useProgram(shaderProgramMap);
shaderProgramMap.ViewMatrixUniform = gl.getUniformLocation(shaderProgramMap, "uViewMatrix");
shaderProgramMap.ModelMatrixUniform = gl.getUniformLocation(shaderProgramMap, "uModelMatrix");
shaderProgramMap.aPositionL = gl.getAttribLocation(shaderProgramMap, 'aPositionL');
gl.enableVertexAttribArray(shaderProgramMap.aPositionL);
shaderProgramMap.aNormalL = gl.getAttribLocation(shaderProgramMap, 'aNormalL');
gl.enableVertexAttribArray(shaderProgramMap.aNormalL);
shaderProgramMap.aTangentL = gl.getAttribLocation(shaderProgramMap, 'aTangentL');
gl.enableVertexAttribArray(shaderProgramMap.aTangentL);
shaderProgramMap.aTexCoord = gl.getAttribLocation(shaderProgramMap, 'aTexCoord');
gl.enableVertexAttribArray(shaderProgramMap.aTexCoord);
shaderProgramMap.uMatrixMVP = gl.getUniformLocation(shaderProgramMap, 'uMatrixMVP');
shaderProgramMap.uMatrixMV = gl.getUniformLocation(shaderProgramMap, 'uMatrixMV');
shaderProgramMap.uColorSampler = gl.getUniformLocation(shaderProgramMap, 'uColorSampler');
shaderProgramMap.uNormalSampler = gl.getUniformLocation(shaderProgramMap, 'uNormalSampler');
shaderProgramMap.uTime = gl.getUniformLocation(shaderProgramMap, 'uTime');
}
So I call the function "changeShaderBasic" first, and when I want to draw a surface with a normal map I do something like this:
changeShaderNormal();
*Draw the surface*
changeShaderBasic();
If I delete that part of the code it works- So the shaders shader-fs and shader-vs seem to be working fine. The problem seems to be the other shaders (vs and fs) or the function that switchs between shaders.
I have omited the part of the code which the program uses to create textures.
I don't know what I am doing wrong and I don't know how to find the problem.