WebGL attribute is always null - webgl

I'm trying to make a graphic engine in WebGL, but I'm having lots of trouble.
One of this problems is about attributes being null or -1 when I call them with "gl.getUniformLocation".
My main problem with this right now is "aVertexTextureCoords", which is always -1.
I leave here my shaders, just in case they're the problem.
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec4 aVertexColor;
attribute vec2 aVertexTextureCoords;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
uniform mat4 uNMatrix;
uniform float uAlpha;
const int NUM_LIGHTS = 4;
uniform vec4 uMaterialDiffuse;
uniform vec3 uLightPosition[NUM_LIGHTS];
//varyings
varying vec4 vColor;
varying vec2 vTextureCoord;
varying vec3 vNormal;
varying vec3 vLightRay[NUM_LIGHTS];
void main(void) {
//Transformed vertex position
vec4 vertex = uMVMatrix * vec4(aVertexPosition, 1.0);
//Transformed normal position
vNormal = vec3(uNMatrix * vec4(aVertexNormal, 1.0));
//Calculate light ray per each light
for(int i=0; i < NUM_LIGHTS; i++){
vec4 lightPosition = uMVMatrix * vec4(uLightPosition[i], 1.0);
vLightRay[i] = vertex.xyz - lightPosition.xyz;
}
//Final vertex position
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vTextureCoord = aVertexTextureCoords;
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision highp float;
#endif
//object uniforms
uniform bool uWireframe;
uniform vec4 uMaterialAmbient;
uniform vec4 uMaterialDiffuse;
//Incluimos un uniform que asociara la textura a un uniform
uniform sampler2D uSampler;
//light uniforms
const int NUM_LIGHTS = 4;
uniform bool uLightSource;
uniform vec4 uLightAmbient;
uniform vec4 uLightDiffuse[NUM_LIGHTS];
uniform float uCutOff;
//varyings
varying vec2 vTextureCoord;
varying vec3 vNormal;
varying vec3 vLightRay[NUM_LIGHTS];
void main(void)
{
if(uWireframe || uLightSource){
gl_FragColor = uMaterialDiffuse;
}
else{
vec4 Ia = uLightAmbient * uMaterialAmbient; //Ambient component: one for all
vec4 finalColor = vec4(0.0,0.0,0.0,1.0); //Color that will be assigned to gl_FragColor
vec3 N = normalize(vNormal);
vec3 L = vec3(0.0);
float lambertTerm = 0.0;
for(int i = 0; i < NUM_LIGHTS; i++){ //For each light
L = normalize(vLightRay[i]); //Calculate reflexion
lambertTerm = dot(N, -L);
if (lambertTerm > uCutOff){
finalColor += uLightDiffuse[i] * uMaterialDiffuse *lambertTerm; //Add diffuse component, one per light
}
}
//Final color
finalColor += Ia;
finalColor.a = 1.0; //Add ambient component: one for all
gl_FragColor = finalColor * texture2D(uSampler, vTextureCoord); //The alpha value in this example will be 1.0
}
}
</script>
Can somebody tell me what I'm doing wrong?

Calling gl.getUniformLocation for a vertex attribute is wrong because it's an attribute, not a uniform. Replace the call with gl.getAttribLocation.

Related

Webgl - How to make Specular Light not change size

I am trying to implement specular lighting (thats coming from the front) but the light is always changing size in an unnatural way. How do I fix this?
I hardcoded viewerPos to test. I'm using a halfway vector "shortcut" so I have to calculate less things as explained here: https://webglfundamentals.org/webgl/lessons/webgl-3d-lighting-point.html
Video with my lighting implemented: https://streamable.com/j95bz7
// Vertex shader program
const vsSource = `
attribute vec4 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aTextureCoord;
uniform mat4 uNormalMatrix;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
uniform highp vec3 uViewPos;
varying highp vec2 vTextureCoord;
varying highp vec4 vNormal;
varying highp mat4 vModelViewMatrix;
varying highp vec3 vPos;
void main(void) {
gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition;
vTextureCoord = aTextureCoord; //Textura
vModelViewMatrix = uModelViewMatrix;
vPos = (uModelViewMatrix * aVertexPosition).xyz;
vNormal = uNormalMatrix * vec4(aVertexNormal, 1.0);
}
`;
// Fragment shader program
const fsSource = `
varying highp vec2 vTextureCoord;
varying highp vec4 vNormal;
varying highp mat4 vModelViewMatrix;
varying highp vec3 vPos;
uniform sampler2D uSampler;
void main(void) {
// Apply lighting effect
highp vec4 texelColor = texture2D(uSampler, vTextureCoord);
//Luz Ambiente
highp vec3 ambientLight = 0.3 * vec3(1.0, 1.0, 1.0);
//Luz Difusa
highp vec3 directionalLightColor = vec3(1, 1, 1);
highp vec3 directionalVector = vec3(0.0, 0.0, 1.0);
highp float directional = max(dot(vNormal.xyz, normalize(directionalVector)), 0.0);
//Luz Especular
highp vec3 viewerPos = vec3(0, 0, -6); //NOTA: PASSAR PARA SHADERS, NAO DAR HARDCODE
highp vec3 surfaceToLightDirection = (-1.0 * directionalVector);
highp vec3 surfaceToViewDirection = (vPos - viewerPos);
highp vec3 halfVector = normalize(surfaceToLightDirection + surfaceToViewDirection);
highp float specular = max(dot(vNormal.xyz, halfVector), 0.0);
highp vec3 vLighting = ambientLight;// + (directionalLightColor * directional);
gl_FragColor = vec4(texelColor.rgb * vLighting + (specular * 0.5), texelColor.a);
}
`;

How blending image mask?

How can I apply such a mask
to get effect such as bokeh
need to blur edge in mask and apply on image texture. How do that?
Vertex shader:
attribute vec4 a_Position;
void main()
{
gl_Position = a_Position;
}
Fragment shader:
precision lowp float;
uniform sampler2D u_Sampler; // textureSampler
uniform sampler2D u_Mask; // maskSampler
uniform vec3 iResolution;
vec4 blur(sampler2D source, vec2 size, vec2 uv) {
vec4 C = vec4(0.0);
float width = 1.0 / size.x;
float height = 1.0 / size.y;
float divisor = 0.0;
for (float x = -25.0; x <= 25.0; x++)
{
C += texture2D(source, uv + vec2(x * width, 0.0));
C += texture2D(source, uv + vec2(0.0, x * height));
divisor++;
}
C*=0.5;
return vec4(C.r / divisor, C.g / divisor, C.b / divisor, 1.0);
}
void main()
{
vec2 uv = gl_FragCoord.xy / iResolution.xy;
vec4 videoColor = texture2D(u_Sampler, uv);
vec4 maskColor = texture2D(u_Mask, uv);
gl_FragColor = blur(u_Sampler, iResolution.xy, uv);
}
vec4 blurColor = blur(u_Sampler, iResolution.xy, uv);
gl_FragColor = mix(blurColor, videoColor, maskColor.r);
But FYI it's not common to blur in one pass like you have. It's more common to blur in one direction (horizontally), then blur the result of that vertically, then mix the results, blurredTexture, videoTexture, mask.

Phong Shader: Fixed light specular component rotates with camera

I wrote a Phong shader for WebGL. My Scene supports camera rotation using Euler Angles. The light should be fixed in the scene. As soon as I rotate the camera the specular effects on objects move as well. Translation also seems to have strange effects on the specular component. I
(hopefully) made sure that calculations are performed in eye space. I first want to find out if my shaders are correct.
Here is my code:
Vertex Shader
struct Light {
vec3 position;
/* ... */
};
uniform Light u_light;
uniform mat4 u_modelViewProjMat;
uniform mat4 u_modelViewMat;
uniform mat4 u_viewMat;
uniform mat3 u_normalMat;
in vec3 a_position;
in vec3 a_normal;
in vec2 a_texCoord;
out vec2 v_texCoord;
out vec3 v_normal;
out vec3 f_position;
out vec3 v_lightPos;
void main() {
v_normal = u_normalMat * a_normal;
v_texCoord = a_texCoord;
f_position = vec3(u_modelViewMat * vec4(a_position, 1.0));
v_lightPos = vec3(u_viewMat * vec4(u_light.position, 1.0));
gl_Position = u_modelViewProjMat * vec4(a_position, 1.0);
}
Fragment Shader
struct Material {
sampler2D diffuse;
vec3 specular;
float shininess;
};
struct Light {
/* ... */
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform Material u_material;
uniform Light u_light;
uniform vec3 u_eyePosition;
in vec2 v_texCoord;
in vec3 v_normal;
in vec3 f_position;
in vec3 v_lightPos;
out vec4 outColor;
void main() {
vec3 texture = vec3(texture(u_material.diffuse, v_texCoord));
// ambient
vec3 ambient = u_light.ambient * texture;
// diffuse
vec3 normal = normalize(v_normal);
vec3 lightDir = normalize(v_lightPos - f_position);
float diff = max(dot(normal, lightDir), 0.0);
vec3 diffuse = u_light.diffuse * diff * texture;
// specular
vec3 viewDir = normalize(u_eyePosition - f_position);
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_material.shininess);
vec3 specular = u_light.specular * (spec * u_material.specular);
outColor = vec4((ambient + diffuse + specular), 1.0);
}
f_position is a camera space position, so to get the viewDir vector for your specular component you should only perform vec3 viewDir = normalize(-f_position); or work with world space coordinates

GLSL Shader Error "Constructor calls may not have precision"

GLSL Shader Error
ERROR: 0:1: '(' : syntax error: Constructor calls may not have precision
I'm seeing this error with Xcode 6 on an iOS 8 app based on GLPaint demo... (works fine in iOS7)
I also noticed they no longer use the "STRINGIFY" thing in version 1.13 of GLPaint demo.
.vsh
static const char* BaseVS = STRINGIFY
(
attribute highp vec4 inVertex;
uniform highp mat4 MVP;
uniform highp float pointSize;
uniform highp vec4 vertexColor;
uniform highp float brushRotation;
varying highp vec4 color;
void main()
{
gl_Position = MVP * inVertex;
gl_PointSize = pointSize;
color = vertexColor;
}
);
.fsh
static const char* BaseFS = STRINGIFY
(
uniform sampler2D texture;
uniform sampler2D normalMap;
uniform highp float brushRotation;
varying highp vec4 color;
varying highp vec3 normal;
varying highp vec3 lightDir;
varying highp vec3 eyeVec;
precision highp float;
void main (void)
{
highp float vRotation = (brushRotation/180.0)*3.14;;
highp float mid = 0.5;
highp vec2 rotated = vec2(cos(vRotation) * (gl_PointCoord.x - mid) + sin(vRotation) * (gl_PointCoord.y - mid) + mid,
cos(vRotation) * (gl_PointCoord.y - mid) - sin(vRotation) * (gl_PointCoord.x - mid) + mid);
highp vec4 rotatedTexture = texture2D( texture, rotated);
gl_FragColor = color * rotatedTexture;
}
);
The problem was in a method used for random generation. I removed the "high" before the vec2() construction. (Sigh)
highp float rand(highp vec2 co)
{
return fract(sin(dot(co.xy ,highp vec2(12.9898,78.233))) * 43758.5453);
}

iPad Opengl ES program works fine on simulator but not device

For the device, all of my shaders load fine except one. For this shader program I get "Fragment program failed to compile with current context state" error, followed by a similar error for the vertex shader when I make a call to glGetProgramInfoLog(...);
Vertex shader:
#version 100
uniform mat4 Projection;
uniform mat4 Modelview;
uniform mat4 Rotation;
uniform vec3 Translation;
uniform vec4 LightDirection;
uniform vec4 MaterialDiffuse;
uniform float MaterialShininess;
attribute vec3 position;
attribute vec3 normal;
varying vec4 color;
varying float specularCoefficient;
void main() {
vec3 _normal = normalize(mat3(Modelview[0].xyz, Modelview[1].xyz, Modelview[2].xyz)*normal);
// There is an easier way to do the above using typecast, but is apparently broken
float NdotL = dot(-_normal, normalize(vec3(LightDirection)));
if(NdotL < 0.0){
NdotL = 0.0;
}
color = NdotL * MaterialDiffuse;
float NdotO = dot(-_normal, vec3(0.0, 0.0, -1.0));
if(NdotO < 0.0){
NdotO = 0.0;
}
specularCoefficient = pow(NdotO, MaterialShininess);
vec3 p = position + Translation;
gl_Position = Projection*Modelview*vec4(p, 1.0);
}
Fragment shader:
#version 100
precision mediump float;
varying vec4 color;
varying float specularCoefficient;
uniform vec4 MaterialSpecular;
void main(){
gl_FragColor = vec4((color + specularCoefficient*MaterialSpecular).rgb, 1.0);
}
I am not sure what is going on, especially since I have a similar program that is exactly as above with the addition of texture coordinates. Also, I checked the compile status of each shader when I linked the programs using glGetShaderiv(theShader, GL_COMPILE_STATUS, &result) and they all checked out fine. Any ideas?
Changing the line
gl_FragColor = vec4((color + specularCoefficient*MaterialSpecular).rgb, 1.0);
in the fragment shader to
gl_FragColor = vec4((1.0*color + specularCoefficient*MaterialSpecular).rgb, 1.0);
fixes the problem. I suspect it has something to do with precision related to the varying variable color, for a reordering of the line to
gl_FragColor = vec4((MaterialSpecular + specularCoefficient*color).rgb, 1.0);
works as well.

Resources