I have a simple vertex and fragment shader that work and draw something. In the vertex shader I set the variable fs_uv, but I don't use it in the fragment shader. However if I comment out this line or change it to just fs_uv = coord; the shader stops drawing. What would cause this?
Vertex shader:
#version 300 es
precision mediump float;
precision mediump int;
precision lowp sampler2D;
precision lowp sampler2DArray;
in vec4 uv;
out vec2 fs_uv;
flat out uint draw_id;
uniform mat4 matrix;
void main() {
vec2 coord = vec2(gl_VertexID >> 1, gl_VertexID & 1);
fs_uv = uv.xy + coord * uv.zw;
gl_Position = matrix * vec4(vec2(100.0f) * coord, 0.0f, 1.0f);
}
Fragment shader:
#version 300 es
precision mediump float;
precision mediump int;
precision lowp sampler2D;
precision lowp sampler2DArray;
in vec2 fs_uv;
out vec4 color;
void main() {
color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
Related
I have variable in vertex shader "uIsTeapot".
uniform float uIsTeapot;
Vertex shader work with it very well, but fragment shader don't see it. If I use
if (uIsTeapot == 0.0)
then an error occured
"uIsTeapot": undeclared identifier
but I defined it in vertex shader. If I define uIsTeapot in both shaders as uniform, then program say "Could not initialise shaders" since program don't pass veryfication
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
EDITED:
I add mediump to variables and now program compiled without errors, but result is one object on screen, but I draw two object.
Vertex shader
attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aTextureCoord;
attribute vec4 aVertexColor;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
uniform mat3 uNMatrix;
uniform vec3 uAmbientColor;
uniform vec3 uPointLightingLocation;
uniform vec3 uPointLightingColor;
uniform mediump float uIsTeapot;
//varying float vIsTeapot;
varying vec2 vTextureCoord;
varying vec3 vLightWeighting;
varying vec4 vColor;
void main(void) {
if (uIsTeapot == 1.0) {
vec4 mvPosition = uMVMatrix * vec4(aVertexPosition, 1.0);
gl_Position = uPMatrix * mvPosition;
vec3 lightDirection = normalize(uPointLightingLocation - mvPosition.xyz);
vec3 transformedNormal = uNMatrix * aVertexNormal;
float directionalLightWeighting = max(dot(transformedNormal, lightDirection), 0.0);
directionalLightWeighting = 100.0;
vLightWeighting = uAmbientColor + uPointLightingColor * directionalLightWeighting;
vTextureCoord = aTextureCoord;
}
if (uIsTeapot == 0.0) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vColor = aVertexColor;
} }
Fragment shader
precision mediump float;
varying vec2 vTextureCoord;
varying vec3 vLightWeighting;
varying vec4 vColor;
uniform sampler2D uSampler;
uniform mediump float uIsTeapot;
//varying float vIsTeapot;
void main(void) {
if (uIsTeapot == 1.0) {
vec4 textureColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
gl_FragColor = vec4(textureColor.rgb * vLightWeighting, textureColor.a);
} else {
gl_FragColor = vColor;
}
}
You need to declare it in both shaders, with the same precision.
What do you mean by:
then program don't work right.
Can you post your vertex shader and your fragment shader? I suspect you are relying on the default precision, and it is likely that you are using highp in the vertex shader and mediump in the fragment shader
Try using:
uniform mediump float uIsTeapot;
... in both vertex shader and fragment shader.
My phong fragment shader is not shading anything, just making everything black.
This is my fragment shader
precision mediump float;
varying vec3 vposition;
varying vec3 vnormal;
varying vec4 vcolor;
varying vec3 veyePos;
void main() {
vec3 lightPos = vec3(0,0,0);
vec4 s = normalize(vec4(lightPos,1) - vec4(veyePos,1));
vec4 r = reflect(-s,vec4(vnormal, 1));
vec4 v = normalize(-vec4(veyePos, 1));
float spec = max( dot(v,r),0.0 );
float diff = max(dot(vec4(vnormal,1),s),0.0);
vec3 diffColor = diff * vec3(1,0,0);
vec3 specColor = pow(spec,3.0) * vec3(1,1,1);
vec3 ambientColor = vec3(0.1,0.1,0.1);
gl_FragColor = vec4(diffColor + 0.5 * specColor + ambientColor, 1);
}
This is my vertex shader
uniform mat4 uMVPMatrix;
uniform mat4 uMVMatrix;
uniform vec3 eyePos;
attribute vec4 aPosition;
attribute vec4 aColor;
attribute vec4 aNormal;
varying vec4 vcolor;
varying vec3 vposition;
varying vec3 vnormal;
varying vec3 veyePos;
void main() {
mat4 normalMat = transpose(inverse(uMVMatrix));
vec4 vertPos4 = uMVMatrix * vec4(vec3(aPosition), 1.0);
vposition = vec3(vertPos4) / vertPos4.w;
vcolor = aColor;
veyePos = eyePos;
vnormal = vec3(uMVMatrix * vec4(vec3(aNormal),0.0));
gl_Position = uMVPMatrix * aPosition;
}
MVMatrix is model-view matrix
MVPMatrix is model-view-projection matrix
first of all your lighting equations are incorrect:
vector s that you use to calculate the diffuse color should be a unit vector that originates at your vertex (vposition) towards your light. so it would be
s = normalize(lightPos - vposition)
also lightPos should be given in camera space and not in world space (so you should multiply it by your MV matrix)
vector r is the reflection of s around the normal so i dont understand why you take -s also the normal there should be in non-homegenous coordinates so it would be:
r = reflect(s,vnormal)
and finally v is the viewing ray (multiplied by -1) so it should be the vector that originates at vposition and goes towards eyepos.
v = normalize(veyepos - vposition)
also in your vertex shader veyepos (assuming it is the position of your camera) should not be varying (should be flat variable) because you dont want to interpolate it.
in your vertex shader you calculate normalMat but you forgot to use it when calculating your normals in camera space.
also normalMat should be mat3 because it is the inverse transpose of the
3by3 block of your MV matrix originating at (0,0)
** in order to be efficient you should calculate your normalMat on the cpu and pass it as a uniform to your vertex shader
hope this helps
I'm very new to OpenGL, GLSL and WebGL. I'm trying to get this sample code to work in a tool like http://shdr.bkcore.com/ but I can't get it to work.
Vertex Shader:
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
}
Fragment Shader:
precision highp float;
uniform float time;
uniform vec2 resolution;
varying vec3 fPosition;
varying vec3 fNormal;
uniform sampler2D tex0;
void main()
{
float border = 0.01;
float circle_radius = 0.5;
vec4 circle_color = vec4(1.0, 1.0, 1.0, 1.0);
vec2 circle_center = vec2(0.5, 0.5);
vec2 uv = gl_TexCoord[0].xy;
vec4 bkg_color = texture2D(tex0,uv * vec2(1.0, -1.0));
// Offset uv with the center of the circle.
uv -= circle_center;
float dist = sqrt(dot(uv, uv));
if ( (dist > (circle_radius+border)) || (dist < (circle_radius-border)) )
gl_FragColor = bkg_color;
else
gl_FragColor = circle_color;
}
I figured that this code must be from an outdated version of the language, so I changed the vertex shader to:
precision highp float;
attribute vec2 position;
attribute vec3 normal;
varying vec2 TextCoord;
attribute vec2 textCoord;
uniform mat3 normalMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
varying vec3 fNormal;
varying vec3 fPosition;
void main()
{
gl_Position = vec4(position, 0.0, 1.0);
TextCoord = vec2(textCoord);
}
That seemed to fix the error messages about undeclared identifiers and not being able to "convert from 'float' to highp 4-component something-or-other", but I have no idea if, functionally, this will do the same thing as the original intended.
Also, when I convert to this version of the Vertex Shader I have no idea what I'm supposed to do with this line in the Fragment Shader:
vec2 uv = gl_TexCoord[0].xy;
How do I convert this line to fit in with the converted vertex shader and how can I be sure that the vertex shader is even converted correctly?
gl_TexCoord is from desktop OpenGL, and not part of OpenGL ES. You'll need to create a new user-defined vec2 varying to hold the coordinate value.
I have a 3x3 homography matrix that works correctly with OpenCV's warpPerspective, but I need to do the warping on GPU for performance reasons. What is the best approach? I tried multiplying in the vertex shader to get the texture coordinates and then render a quad, but I get strange distortions. I'm not sure if it's the interpolation not working as I expect. Attaching output for comparison (it involves two different, but close enough shots).
Absolute difference of warp and other image from GPU:
Composite of warp and other image in OpenCV:
EDIT:
Following are my shaders: the task is image rectification (making epilines become scanlines) + absolute difference.
// Vertex Shader
static const char* warpVS = STRINGIFY
(
uniform highp mat3 homography1;
uniform highp mat3 homography2;
uniform highp int width;
uniform highp int height;
attribute highp vec2 position;
varying highp vec2 refTexCoords;
varying highp vec2 curTexCoords;
highp vec2 convertToTexture(highp vec3 pixelCoords) {
pixelCoords /= pixelCoords.z; // need to project
pixelCoords /= vec3(float(width), float(height), 1.0);
pixelCoords.y = 1.0 - pixelCoords.y; // origin is in bottom left corner for textures
return pixelCoords.xy;
}
void main(void)
{
gl_Position = vec4(position / vec2(float(width) / 2.0, float(height) / 2.0) - vec2(1.0), 0.0, 1.0);
gl_Position.y = -gl_Position.y;
highp vec3 initialCoords = vec3(position, 1.0);
refTexCoords = convertToTexture(homography1 * initialCoords);
curTexCoords = convertToTexture(homography2 * initialCoords);
}
);
// Fragment Shader
static const char* warpFS = STRINGIFY
(
varying highp vec2 refTexCoords;
varying highp vec2 curTexCoords;
uniform mediump sampler2D refTex;
uniform mediump sampler2D curTex;
uniform mediump sampler2D maskTex;
void main(void)
{
if (texture2D(maskTex, refTexCoords).r == 0.0) {
discard;
}
if (any(bvec4(curTexCoords[0] < 0.0, curTexCoords[1] < 0.0, curTexCoords[0] > 1.0, curTexCoords[1] > 1.0))) {
discard;
}
mediump vec4 referenceColor = texture2D(refTex, refTexCoords);
mediump vec4 currentColor = texture2D(curTex, curTexCoords);
gl_FragColor = vec4(abs(referenceColor.r - currentColor.r), 1.0, 0.0, 1.0);
}
);
I think you just need to do the projection per pixel. Make refTexCoords and curTexCoords at least vec3, then do the /z in the pixel shader before texture lookup. Even better use the textureProj GLSL instruction.
You want to do everything that is linear in the vertex shader, but things like projection need to be done in the fragment shader per pixel.
This link might help with some background: http://www.reedbeta.com/blog/2012/05/26/quadrilateral-interpolation-part-1/
i'm trying simple texture splatting on ios opengl es 2.0 (ipad). I have 4 tiled textures in pvrt compressed atlas (2x2 tiles). 4 single textures on 4 texture units was terribly slow.
vertex shader:
attribute lowp vec4 position;
attribute lowp vec2 tex0;
varying lowp vec2 surfCoord;
uniform mat4 projection_modelview;
uniform lowp float uv_coef;
varying lowp vec2 texCoord1;
varying lowp vec2 texCoord2;
varying lowp vec2 texCoord3;
varying lowp vec2 texCoord4;
void main()
{
gl_Position = projection_modelview * position;
vec2 texCoord = fract(vec2(position.x / uv_coef, position.y / uv_coef));
texCoord1 = texCoord * 0.5;
texCoord2 = texCoord1 + vec2(0.5, 0);
texCoord3 = texCoord1 + vec2(0, 0.5);
texCoord4 = texCoord1 + vec2(0.5, 0.5);
surfCoord = tex0;
}
fragment shader:
uniform sampler2D texture0; // surface alpha map
uniform sampler2D texture1; // atlas
varying lowp vec2 surfCoord;
varying lowp vec2 texCoord1;
varying lowp vec2 texCoord2;
varying lowp vec2 texCoord3;
varying lowp vec2 texCoord4;
void main()
{
lowp vec4 surfTexel = texture2D(texture0, surfCoord);
lowp vec4 texel1 = texture2D(texture1, texCoord1);
lowp vec4 texel2 = texture2D(texture1, texCoord2);
lowp vec4 texel3 = texture2D(texture1, texCoord3);
lowp vec4 texel4 = texture2D(texture1, texCoord4);
texel1 *= surfTexel.r;
texel2 = mix(texel1, texel2, surfTexel.g);
texel3 = mix(texel2, texel3, surfTexel.b);
gl_FragColor = mix(texel3, texel4, surfTexel.a);
}
shows this one:
(source: inputwish.com)
My problem is probably texture unit interpolators but i don't how to resolve. I don't see mistake in my shaders. Any advice please?
mistake is using fract in vertex shader. it's too early. It should be in fragment shader:
lowp vec4 texel1 = texture2D(texture1, fract(texCoord) * 0.5);
lowp vec4 texel2 = texture2D(texture1, fract(texCoord) * 0.5 + vec2(0.5, 0.0));
lowp vec4 texel3 = texture2D(texture1, fract(texCoord) * 0.5 + vec2(0.0, 0.5));
lowp vec4 texel4 = texture2D(texture1, fract(texCoord) * 0.5 + vec2(0.5, 0.5));
... and mix them together..
anyway it's slow because dependent texture reads on ipad ios.