I am implementing an android app with OpenGL and C++, I am rendering some triangles with different Y position, all of them are in the X-Z plane, the camera is Orthographic projection with near value 3 for example.
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
The orthographic projection is:
projectionMatrix = glm::ortho(-(width/2.f)/zoom, (width/2.f)/zoom, -(height/2.f)/zoom,(height/2.f)/zoom,near,far);
these values are
projectionMatrix = glm::ortho(-100, 100, -197,197,3,50);
sometimes I get the triangles seem to have Z-Fighting although they have different Y values, the camera looks at them from above.
vertexShader = "#version 300 es\n"
"precision highp float;\n"
"layout (location = 0) in vec3 position;\n"
"layout (location = 1) in vec3 normal;\n"
"layout (location = 2) in vec2 texCoord;\n"
"\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"\n"
"out vec2 TexCoords;\n"
"out vec3 Normal;\n"
"out vec3 FragPos;\n"
"\n"
"void main(){\n"
" Normal = mat3(transpose(inverse(model))) * normal;\n"
" TexCoords = texCoord;\n"
" FragPos = vec3(model * vec4(position, 1.0));\n"
" gl_Position = projection * view * model * vec4(position, 1.0);\n"
"}";
fragmentShader = "#version 300 es\n"
"precision highp float;\n"
"\n"
"struct DirectLight{\n"
" vec3 Direction;"
" vec3 color;\n"
" float intensity;\n"
"};\n"
"out vec4 glFragColor;\n"
"\n"
"in vec2 TexCoords;\n"
"in vec3 Normal;\n"
"in vec3 FragPos;\n"
"\n"
"uniform int hasTexture;\n"
"uniform int hasSpecular;\n"
"uniform float alpha;\n"
"uniform vec3 ViewPos;\n"
"\n"
"uniform sampler2D map_diffuse;\n"
"uniform sampler2D map_specular;\n"
"\n"
"uniform vec3 diffuse;\n"
"uniform vec3 specular;\n"
"uniform float shininess;\n"
"uniform DirectLight Sun1;\n"
"vec3 calcLight(DirectLight light,vec3 diffColor,vec3 specColor){"
" vec3 normal = normalize(Normal);\n"
" vec3 lightDir = normalize(-light.Direction);\n"
" float diffFactor = max(dot(normal,lightDir), 0.0);\n"
" vec3 _diffuse = light.intensity * light.color * diffFactor * diffColor;\n"
" vec3 viewDir = normalize(ViewPos - FragPos);\n"
" vec3 halfwayDir = normalize(lightDir + viewDir);\n"
" float specFactor = pow(max(dot(normal, halfwayDir), 0.0), shininess);\n"
" vec3 _specular = specColor * light.intensity * light.color * specFactor;\n"
" return _diffuse + _specular ;\n"
"}"
"void main(){\n"
" vec4 diffColor;\n"
" vec4 specColor;\n"
" if(hasTexture == 1)\n"
" diffColor = texture(map_diffuse, TexCoords);\n"
" else\n"
" diffColor = vec4(diffuse,alpha);\n"
" if(hasSpecular == 1)\n"
" specColor = texture(map_specular, TexCoords);\n"
" else\n"
" specColor = vec4(specular,alpha);\n"
" vec4 _ambient = vec4(0.4,0.4,0.4,alpha) * diffColor;\n"
" vec4 result = vec4("
" calcLight(Sun1,diffColor.xyz,specColor.xyz),alpha)"
" + _ambient;"
" float gamma = 2.2;\n"
" result = pow(result, vec4(1.0/gamma));\n"
" glFragColor = result;\n"
"}";
Related
The code inside my fragment shader is:
"precision mediump float;\n" +
"varying vec2 vTextureCoord;\n" +
"uniform sampler2D sTexture;\n" +
"uniform float Opacity;\n" + // range 0.0 to 1.0
"void main() {\n" +
" gl_FragColor = texture2D(sTexture, vTextureCoord);\n"+
" gl_FragColor.a *= Opacity;\n" +
"}\n";
which works, I tried to add an if inside :
"precision mediump float;\n" +
"varying vec2 vTextureCoord;\n" +
"uniform sampler2D sTexture;\n" +
"uniform float Opacity;\n" + // range 0.0 to 1.0
"void main() {\n" +
" gl_FragColor = texture2D(sTexture, vTextureCoord);\n"+
" gl_FragColor.a *= Opacity;\n" +
" if(gl_FragColor.a < 250){;\n" +
" gl_FragColor.a = 250;\n" +
" }\n" +
"}\n";
and it does not work, I cant figure this one out, I will appreciate some help
I'm having mpvMatrix (mvpMatrix is calculated as model * view * projection using Matrix.multiply()) and passing it to shader and it's ok.
Now i'd like to move multiplication from CPU to GPU (from Matrix.multiply to shader).
If i'm trying to pass model, view and projection martrix separately and multiply them in shader i see nothing.
I'm sure matrix are not null and have real values (as if i multiply them on CPU instead of GPU it's ok), matrix uniform index are >= 0 (they are found in shader). What can be wrong?
Shaders:
private final String vertexShader =
"uniform mat4 u_mMatrix; \n" // Матрица модели
+ "uniform mat4 u_vMatrix; \n" // Матрица модели
+ "uniform mat4 u_pMatrix; \n" // Матрица модели
+ "attribute vec4 a_Position; \n" // Информация о положении вершин.
+ "attribute vec2 a_TexCoordinate; \n" // Per-vertex texture coordinate information we will pass in.
+ "varying vec2 v_TexCoordinate; \n" // This will be passed into the fragment shader.
+ "void main() \n" // Начало программы вершинного шейдера.
+ "{ \n"
+ " v_TexCoordinate = a_TexCoordinate; \n"
+ " mat4 mvMatrix = u_mMatrix * u_vMatrix;"
+ " mat4 mvpMatrix = mvMatrix * u_pMatrix;"
+ " gl_Position = mvpMatrix \n" // gl_Position специальные переменные используемые для хранения конечного положения.
+ " * a_Position; \n" // Умножаем вершины на матрицу для получения конечного положения
+ "} \n"; // в нормированных координатах экрана.
private final String fragmentShader =
"precision mediump float; \n" // Устанавливаем по умолчанию среднюю точность для переменных. Максимальная точность в фрагментном шейдере не нужна.
+ "uniform sampler2D u_Texture; \n" // The input texture.
+ "varying vec2 v_TexCoordinate; \n" // Interpolated texture coordinate per fragment.
+ "void main() \n" // Точка входа для фрагментного шейдера.
+ "{ \n"
+ " gl_FragColor = texture2D(u_Texture, v_TexCoordinate); \n" // Передаем значения цветов.
+ "}";
Binding:
mMatrixHandle = GLES20.glGetUniformLocation(programHandle, "u_mMatrix"); // = 0
vMatrixHandle = GLES20.glGetUniformLocation(programHandle, "u_vMatrix"); // = 2
pMatrixHandle = GLES20.glGetUniformLocation(programHandle, "u_pMatrix"); // = 3
Drawing:
GLES20.glUniformMatrix4fv(mMatrixHandle, 1, false, modelMatrix, 0);
GLES20.glUniformMatrix4fv(vMatrixHandle, 1, false, viewMatrix, 0);
GLES20.glUniformMatrix4fv(pMatrixHandle, 1, false, projectionMatrix, 0);
Actually my matrix multiplication order in shader was wrong, the correct order is:
gl_Position = u_pMatrix * u_mMatrix * u_vMatrix * a_Position;
so the correct shader source is:
private final String vertexShader =
"uniform mat4 u_mMatrix; \n" // Матрица модели
+ "uniform mat4 u_vMatrix; \n" // Матрица модели
+ "uniform mat4 u_pMatrix; \n" // Матрица модели
+ "attribute vec4 a_Position; \n" // Информация о положении вершин.
+ "attribute vec2 a_TexCoordinate; \n" // Per-vertex texture coordinate information we will pass in.
+ "varying vec2 v_TexCoordinate; \n" // This will be passed into the fragment shader.
+ "void main() \n" // Начало программы вершинного шейдера.
+ "{ \n"
+ " v_TexCoordinate = a_TexCoordinate; \n"
+ " gl_Position = u_pMatrix * u_mMatrix * u_vMatrix \n" // gl_Position специальные переменные используемые для хранения конечного положения.
+ " * a_Position; \n" // Умножаем вершины на матрицу для получения конечного положения
+ "} \n"; // в нормированных координатах экрана.
For my android application, I want to apply brightness and contrast shader on same image.
At present I am using gpuimage plugin. In that I found two separate program for brightness and contrast as per the following.
public static final String CONTRAST_FRAGMENT_SHADER = "" +
"varying highp vec2 textureCoordinate;\n" +
" \n" +
" uniform sampler2D inputImageTexture;\n" +
" uniform lowp float contrast;\n" +
" \n" +
" void main()\n" +
" {\n" +
" lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" +
" \n" +
" gl_FragColor = vec4(((textureColor.rgb - vec3(0.5)) * contrast + vec3(0.5)), textureColor.w);\n" +
" }";
public static final String BRIGHTNESS_FRAGMENT_SHADER = ""
+ "varying highp vec2 textureCoordinate;\n"
+ " \n"
+ " uniform sampler2D inputImageTexture;\n"
+ " uniform lowp float brightness;\n"
+ " \n"
+ " void main()\n"
+ " {\n"
+ " lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n"
+ " \n"
+ " gl_FragColor = vec4((textureColor.rgb + vec3(brightness)), textureColor.w);\n"
+ " }";
Now applying both of the effects I write following code
public static final String CONTRAST_BRIGHTNESS_FRAGMENT_SHADER = ""
+ "varying highp vec2 textureCoordinate;\n"
+ " uniform sampler2D inputImageTexture;\n"
+ "varying highp vec2 textureCoordinate2;\n"
+ " uniform sampler2D inputImageTexture2;\n"
+ " uniform lowp float contrast;\n"
+ " uniform lowp float brightness;\n"
+ " \n"
+ " void main()\n"
+ " {\n"
+ " lowp vec4 textureColorForContrast = texture2D(inputImageTexture, textureCoordinate);\n"
+ " \n"
+ " lowp vec4 contastVec4 = vec4(((textureColorForContrast.rgb - vec3(0.5)) * contrast + vec3(0.5)), textureColorForContrast.w);\n"
+ " lowp vec4 textureColorForBrightness = texture2D(inputImageTexture2, textureCoordinate2);\n"
+ " \n"
+ " lowp vec4 brightnessVec4 = vec4((textureColorForBrightness.rgb + vec3(brightness)), textureColorForBrightness.w);\n"
+ " gl_FragColor = contastVec4 + brightnessVec4;\n" + " }";
Doesn't able to get desire result. I can't able to figure out what I have to do next?
What program I have to write?
Why would you add the 2 results in the end? What you need to do is fetch a texel and do the 2 mathematical operations on it. Try this:
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
lowp vec3 contrastedColor = ((textureColor.rgb - vec3(0.5)) * contrast + vec3(0.5));
gl_FragColor = vec4((contrastedColor + vec3(brightness)), textureColor.w);
Still this can produce a different result then using the 2 separate shaders so let's analyse a bit what goes on:
grab a texture color
apply contrast method
write colour to buffer (at this point the colour values are clamped in range [.0, 1.0])
grab a texture color
apply brightness
write colour to buffer
So what you should add is clamping the contrast colour contrastedColor to [0,1]. As for what M. Coleman said it is true you need to consider the possibility of the result being different because of fetching multiple texels BUT in your specific case that can NOT produce a different result and you are all good to go with it. As for the blending the assumption is being either disabled or (GL_ONE, GL_ZERO) which is the same thing (some other blending types might work as well).
I have an android app in which I use openGL to make some neat image effects.
The base setup is that I continually draw the buffer to one of two textures, then draw on top of that texture the next frame (essentially a simulation), to give the effect that the same image keeps getting manipulated.
I'm trying to add a fade effect to this, in which I darken the background, then draw on top of that, but I'm getting a very strange artifact from this. Here is my fragment shader:
private final String mCompositeFragmentShader =
"#extension GL_OES_EGL_image_external : require\n" +
"precision mediump float;\n" +
"varying vec2 bTextureCoord;\n" +
"varying vec2 vTextureCoord;\n" +
"uniform samplerExternalOES sTexture;\n" +
"uniform sampler2D bufferTexture;\n" +
"uniform float gamma; \n" +
"void main() {\n" +
" vec4 camera = texture2D(sTexture, vTextureCoord);\n" +
" camera.r = pow(camera.r, 1.0/gamma);\n" +
" camera.g = pow(camera.g, 1.0/gamma);\n" +
" camera.b = pow(camera.b, 1.0/gamma);\n" +
" vec4 bg = texture2D(bufferTexture, bTextureCoord);\n" +
" vec3 color = max(camera.rgb, bg.rgb -vec3(.02, .02, .02));\n"+
" gl_FragColor = vec4(color,1.0);\n" +
"}\n";
with the relevant bit of code being:
vec3 color = max(camera.rgb, bg.rgb -vec3(.02, .02, .02));
So I would expect light areas to eventually fade to black over time. However, instead of black it's fading to a magenta grid:
You can see that the gridding is different for each triangle being drawn on the screen (I'm only drawing two triangles).
Here is the vertex shader, just in case:
"uniform mat4 uMVPMatrix;\n" +
"uniform mat4 uSTMatrix;\n" +
"attribute vec4 aPosition;\n" +
"attribute vec4 aTextureCoord;\n" +
"varying vec4 tempCoords;" +
"varying vec2 vTextureCoord;\n" +
"varying vec2 bTextureCoord;\n" +
"void main() {\n" +
" gl_Position = aPosition;\n" +
" bTextureCoord = aTextureCoord.xy;\n" +
" tempCoords = aTextureCoord;\n" +
" tempCoords.y = aTextureCoord.y * ("+previewSize.height+".0 /"+previewSize.width+".0);\n" +
" vTextureCoord = (uSTMatrix * tempCoords).xy;\n" +
"}\n";
Anyone have any idea what's causing this, and how to fix it?
How can I pass a float value to fragment shader ?
This is my code on android:
int aUseTexture = GLES20.glGetAttribLocation(program, "uUseTexture");
GLES20.glUniform1f(aUseTexture, 1.0f);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
Here is my shader:
String verticesShader =
"uniform mat4 uScreen;\n" +
"attribute vec2 aPosition;\n" +
"attribute vec3 aColor;\n" +
"attribute vec2 aTexPos; \n" +
"varying vec2 vTexPos; \n" +
"varying vec3 vColor;\n" +
"void main() {\n" +
" vTexPos = aTexPos; \n" +
" gl_Position = uScreen * vec4(aPosition.xy, 0.0, 1.0);\n" +
" vColor = aColor;\n" +
"}";
// Our fragment shader. Just return vColor.
// If you look at this source and just said 'WTF?', remember
// that all the attributes are defined in the VERTEX shader and
// all the 'varying' vars are considered OUTPUT of vertex shader
// and INPUT of the fragment shader. Here we just use the color
// we received and add a alpha value of 1.
String fragmentShader =
"uniform float uUseTexture; \n" +
"uniform sampler2D uTexture;\n" +
"precision mediump float;\n"+
"varying vec2 vTexPos; \n" +
"varying vec3 vColor;\n" +
"void main(void)\n" +
"{\n" +
" if ( uUseTexture != 1.0 ) \n" +
" gl_FragColor = vec4(vColor.xyz, 1); \n" +
" else \n" +
" gl_FragColor = texture2D(uTexture, vTexPos); \n" +
//" gl_FragColor = vec4(vColor.xyz, 1);\n" +
"}";
You can see the if statement in the fragment shader , that is the one i tried to check if i pass in 1.0 it should do texture else use color.
You are probably using the wrong function call for "uniform variable". Try glGetUniformLocation() as follow:
int aUseTexture = GLES20.glGetUniformLocation(program, "uUseTexture");
Also, the floating point testing (uUseTexture != 1.0) may not be always reliable all the time. You may want to use an integer type.
As far as I know you have to pass the value through the vertex shader before it can get to the fragment shader. e.g. add "uniform float uUseTexture_in; \n" and "varying float uUseTexture; \n" at the top of the vertex shader, in the main function add "uUseTexture = uUseTexture_in;". And your shader should work