How to bind a vec2&vec3 variable with OpengGL fragment shader? - java

I'm devloping a android OpenGL ES app, here is my fragment shader snippet:
uniform sampler2D inputImageTexture;
varying highp vec2 textureCoordinate;
uniform lowp vec2 vignetteCenter;
uniform lowp vec3 vignetteColor;
uniform highp float vignetteStart;
uniform highp float vignetteEnd;
void main()
{
lowp vec4 sourceImageColor = texture2D(inputImageTexture, textureCoordinate);
lowp float d = distance(textureCoordinate, vec2(vignetteCenter.x, vignetteCenter.y));
lowp float percent = smoothstep(vignetteStart, vignetteEnd, d);
gl_FragColor = vec4(mix(sourceImageColor.rgb, vignetteColor, percent), sourceImageColor.a);
}
My problem is that I want to bind a variable with GLSL's vignetteCenter and vignetteColor above, I don't know whick kind of Java Type object correspond to vec2 and vec3? GLES20.glUniform2f or GLES20.glUniform2fv, which one should I use?

GLES20.glUniform2f will allow you to assign ONE vector of 2 floats to your uniform variable.
GLES20.glUniform2fv will allow you to assign N vectors of 2 floats to your uniform variable.
So, given two floats f1 and f2, you can either use
GLES20.glUniform2f(myVariablePosition,f1,f2);
or
float[] myVector = {f1,f2};
GLES20.glUniform2f(myVariablePosition,1,myVector);
where 1 there means only 1 vector of 2 floats is passed.
If you wanted to pass an array of vectors of 2 floats then you would do:
float[] myVector = {f1,f2,....,f(N*2)};
GLES20.glUniform2f(myVariablePosition,N,myVector);

Related

Why is my uniform not initializing in openGL?

Why are my uniform vector and float not being initialized? My shader code compiles correctly, my shader is compiling properly, but when I try to get the uniform location of my vec4 lightDirection, and floats specularFactor and diffuseFactor, it gives me an error. Note I haven't actually used these uniforms for anything yet, however, that shouldn't matter.
Here is my vertex shader, which gets all uniform locations properly:
#version 330
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texture_coord;
layout (location = 2) in vec3 normal;
layout (location = 3) in vec3 fNormal;
uniform mat4 worldMat;
uniform mat4 projection;
uniform mat4 transform;
out vec2 tex;
out vec3 n;
out vec3 fn;
void main() {
fn=fNormal;
n=normal;
tex = texture_coord;
gl_Position = projection * worldMat * transform * vec4(position, 1);
}
Here is my fragment shader, which only gets the texture sample uniform location:
#version 330
uniform sampler2D sampleTexture;
uniform vec4 lightDirection;
uniform float specularFactor;
uniform float diffuseFactor;
in vec2 tex;
in vec3 n;
in vec3 fn;
out vec4 fragColor;
void main() {
fragColor=texture(sampleTexture, tex);
}
Here is the method I use to get uniform locations (I am using Java):
public int loadUniform(String uniformName)throws Exception{
int iD= glGetUniformLocation(program,uniformName);
System.out.println("PROGRAM: "+program+" UNIFORM: "+uniformName+" "+iD);
if(iD==-1) {
throw new Exception("uniform:"+uniformName+" not initialized");
}
return iD;
}
Now, here is what is printed in console by print statment/exception. Am confusion. Numbers definitely seem wrong, but whatevs. I don't understaaaaand.
java.lang.Exception: uniform:lightDirection not initialized
at shader_src.Shader.loadUniform(Shader.java:273)
at shader_src.StaticShader.initValues(StaticShader.java:51)
at application.Main.main(Main.java:94)
PROGRAM: 4 UNIFORM: worldMat 9
PROGRAM: 4 UNIFORM: projection 5
PROGRAM: 4 UNIFORM: transform 0
PROGRAM: 4 UNIFORM: sampleTexture 4
PROGRAM: 4 UNIFORM: lightDirection -1
The glsl compiler and linker optimizes the code. Unnecessary code will be removed, and unnecessary uniforms and attributes will not become active program resources. If uniform variables are not used or are only used in a part of the code that is itself optimized out, they do not become active program resources. lightDirection, specularFactor and diffuseFactor are unused variables and therefore not active resources thus no active resources and therefore you cannot get a uniform location for these variables.

Phone unable to compile shader

I have a project I'm working on in libGDX. I'm running tests on a distance field font and I've run into issues while compiling the shader on my Android phone (Galaxy Core 2 4.4.2). When deployed on my phone I get errors while the desktop app works fine (mostly - I'll get to that).
I'll take you through what I've been trying.
I want to be able to enable and disable having a font border during run time, and I can do this fine on the desktop app using the following shader and methods.
.frag:
#ifdef GL_ES
precision mediump float;
#else
#define LOWP
#endif
uniform sampler2D u_texture;
uniform float u_lower;
uniform float u_upper;
varying vec4 v_color;
uniform vec4 u_outlineColor;
uniform float u_enableOutline;
varying vec2 v_texCoord;
const float smoothing = 1.0/12.0;
const float outlineWidth = 3.0/12.0; //will need to be tweaked
const float outerEdgeCenter = 0.5 - outlineWidth; //for optimizing below calculation
void main() {
float distance = texture2D(u_texture, v_texCoord).a;
if (u_enableOutline > 0){
float alpha = smoothstep(outerEdgeCenter - smoothing, outerEdgeCenter + smoothing, distance);//Bigger to accomodate outline
float border = smoothstep(0.45 - smoothing, 0.55 + smoothing, distance);
gl_FragColor = vec4( mix(u_outlineColor.rgb, v_color.rgb, border), alpha );
}
else{
float alpha = smoothstep(0.5 - smoothing, 0.5 + smoothing, distance);
gl_FragColor = vec4(v_color.rgb, alpha);
}
}
.vert:
uniform mat4 u_projTrans;
attribute vec4 a_position;
attribute vec2 a_texCoord0;
attribute vec4 a_color;
varying vec4 v_color;
varying vec2 v_texCoord;
void main() {
gl_Position = u_projTrans * a_position;
v_texCoord = a_texCoord0;
v_color = a_color;
}
With the distance font method to enable / disable the outline being:
public void enableOutline(float enable) {
ENABLE_OUTLINE = enable;
}
Where ENABLE_OUTLINE is passed to the shader by
distanceFieldShader.setUniformf("u_enableOutline", ENABLE_OUTLINE);
In this set up, running on my phone gives the following error:
"cannot compare float to int"
referencing this line in the .frag
if (u_enableOutline > 0){
Fair enough I say, so I change the data type like so:
uniform int u_enableOutline;
And the method to pass through an int:
public void enableOutline(int enable) {
ENABLE_OUTLINE = enable;
}
BUT there is no way to pass an int to the shader (which is why I chose to use floats, see this image: http://imgur.com/nVTN12i) and because of this my method to enable the outline doesn't work due to mixing up data types.
So my question is: can I get around this somehow so that I can enable and disable a border on my phone given these constraints?
It sounds like the API you are using does not offer you the possibility to use bool and int as Uniforms. The solution of using floats to circumvent this seems to be a good idea.
In your example, the problem you are having is because, unlike C and java, the GLSL compiler does not implicitly convert ints to floats.
what you need to do, is tell the compiler the type of your "0".
By using the syntax, 0.0, the compiler knows that your constant is a float and not an integer.
if (u_enableOutline > 0.0){
should fix your problem

'texture2D' : No matching overloaded function found OpenGL ES2?

I was working on a project, and for that project I had to walk through a book called "OpenGL ES 2 For Android: A quick start guide".
So when I got to texturing, I got the error of:
'texture2D' : No matching overloaded function found
...when I compile the shader.
The shader code:
// Fragment shader
precision mediump float;
uniform sampler2D u_TextureUnit;
varying vec4 v_TextureCoordinates;
void main()
{
gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);
}
// Vertex shader
uniform mat4 u_Matrix;
attribute vec4 a_Position;
attribute vec4 a_TextureCoordinates;
varying vec4 v_TextureCoordinates;
void main()
{
gl_Position = u_Matrix * a_Position;
v_TextureCoordinates = a_TextureCoordinates;
}
I tried the same shaders for my project and for exactly the same code as in the book but it still gives me the same error when I compile the shader, and the viewport on the android device is blank, just the clear color I set is shown.
varying vec4 v_TextureCoordinates;
^^^^
There are exactly two texture2D() overloads in ES 2.0:
vec4 texture2D(sampler2D sampler, vec2 coord)
vec4 texture2D(sampler2D sampler, vec2 coord, float bias)
...neither of which accept a vec4 for coord.
Slice off the last two vector components of v_TextureCoordinates using a swizzle:
gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates.xy );

Getting world position for deferred rendering light pass

I have recently began to build some kind of deferred rendering pipeline for the engine I am working on but I'm stuck at reconstructing the world position from depth. I have looked at quite a few examples where the explain that you need either a world position texture or a depth texture to then use for the correct distance and direction calculation of the light.
My problem is that the so called position texture which assumably is the world position doesn't seem to give me correct data. Therefore I tried to find alternative ways of getting a world position and some have suggested that I should use a depth texture instead but then what?
To make it all more clear this picture shows the textures that I currently have stored:
Position(Top left), Normal(Top right), Diffuse(Bottom left) and Depth(Bottom right).
For the light pass I am trying to use a method which works fine if used in the first pass. When I try the same method for the light pass with the exact same variables it stops working.
Here's my Geometry Vertex Shader:
#version 150
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
in vec4 in_Position;
in vec3 in_Normal;
in vec2 in_TextureCoord;
out vec3 pass_Normals;
out vec4 pass_Position;
out vec2 pass_TextureCoord;
out vec4 pass_Diffuse;
void main(void) {
pass_Position = viewMatrix * modelMatrix * in_Position;
pass_Normals = (viewMatrix * modelMatrix * vec4(in_Normal, 0.0)).xyz;
pass_Diffuse = vec4(1,1,1,1);
gl_Position = projectionMatrix * pass_Position;
}
Geometry Fragment shader:
#version 150 core
uniform sampler2D texture_diffuse;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
in vec4 pass_Position;
in vec3 pass_Normals;
in vec2 pass_TextureCoord;
in vec4 pass_Diffuse;
out vec4 out_Diffuse;
out vec4 out_Position;
out vec4 out_Normals;
void main(void) {
out_Position = pass_Position;
out_Normals = vec4(pass_Normals, 1.0);
out_Diffuse = pass_Diffuse;
}
Light Vertex Shader:
#version 150
in vec4 in_Position;
in vec2 in_TextureCoord;
out vec2 pass_TextureCoord;
void main( void )
{
gl_Position = in_Position;
pass_TextureCoord = in_TextureCoord;
}
Light Fragment Shader:
#version 150 core
uniform sampler2D texture_Diffuse;
uniform sampler2D texture_Normals;
uniform sampler2D texture_Position;
uniform vec3 cameraPosition;
uniform mat4 viewMatrix;
in vec2 pass_TextureCoord;
out vec4 frag_Color;
void main( void )
{
frag_Color = vec4(1,1,1,1);
vec4 image = texture(texture_Diffuse,pass_TextureCoord);
vec3 position = texture( texture_Position, pass_TextureCoord).rgb;
vec3 normal = texture( texture_Normals, pass_TextureCoord).rgb;
frag_Color = image;
vec3 LightPosition_worldspace = vec3(0,2,0);
vec3 vertexPosition_cameraspace = position;
vec3 EyeDirection_cameraspace = vec3(0,0,0) - vertexPosition_cameraspace;
vec3 LightPosition_cameraspace = ( viewMatrix * vec4(LightPosition_worldspace,1)).xyz;
vec3 LightDirection_cameraspace = LightPosition_cameraspace + EyeDirection_cameraspace;
vec3 n = normal;
vec3 l = normalize( LightDirection_cameraspace );
float cosTheta = max( dot( n,l ), 0);
float distance = distance(LightPosition_cameraspace, vertexPosition_cameraspace);
frag_Color = vec4((vec3(10,10,10) * cosTheta)/(distance*distance)), 1);
}
And finally, here's the current result:
So My question is if anyone please can explain the result or how I should do to get a correct result. I would also appreciate good resources on the area.
Yes, using the depth buffer to reconstruct position is your best bet. This will significantly cut down on memory bandwidth / storage requirements. Modern hardware is biased towards doing shader calculations rather than memory fetches (this was not always the case), and the instructions necessary to reconstruct position per-fragment will always finish quicker than if you were to fetch the position from a texture with adequate precision. Now, you just have to realize what the hardware depth buffer stores (understand how depth range and perspective distribution work) and you will be good to go.
I do not see any attempt at reconstruction of world/view space position from the depth buffer in the code your question lists. You are just sampling from a buffer that stores the position in view-space. Since you are not performing reconstruction in this example, the problem has to do with sampling the view-space position... can you update your question to include the internal formats of the G-Buffer textures. In particular, are you using a format that can represent negative values (this is necessary to express position, otherwise negative values are clamped to 0).
On a final note, your position is also view-space and not world-space, a trained eye can tell this immediately by the way the colors in your position buffer are black in the lower-left corner. If you want to debug your position/normal, you should bias/scale the sampled colors into the visible range:
([-1.0, 1.0] -> [0.0, 1.0]) // Vec = Vec * 0.5 + 0.5
You may need to do this when you output some of the buffers if you want to store the normal G-Buffer more efficiently (e.g. in an 8-bit fixed-point texture instead of floating-point).

Invalid fragment shader. Link cannot proceed

At the beginning of my project, I used simple Strings for filling my both Shaders with code. This looked like this:
public final static String chunkDefaultVertexInit = ""
+constantParameters
+"precision mediump float;"
+"uniform mat4 mPMatrix;"
+"uniform mat4 mVMatrix;"
+"uniform mat4 mMMatrix;"
+"uniform mat4 mMVMatrix;"
+"attribute vec4 Vertex;"
+"attribute vec3 Normal;"
+"attribute vec2 TexCoord;"
+"varying vec3 normal;"
+"varying vec2 uv;"
+"varying vec4 positionM;"
+"varying vec4 positionMV;";
etc....
This worked for me, but it was not really clearly. So I thought about how I could make my code a little bit more clean and clearly for everybody. My idea was, to put my whole bunch of code in a real .cc - file and move it into the res/raw folder. No sooner said than done.
I wanted to read out my code via Inputstreams and save it into a String. That also worked fine, and so I fed the shader the String source.
So... now there happend to be a problem, and as I said, I didn't get it yet. I even made me a little bit angry about myself, because I thought about an easy way of fix it and I don't see it.
I even did show my source code I put in... but it looks correct! o.O
Log.i("Llama3D Shader",shaderCode);
(Don't worry about the weird "Debug ID," it's the projects name)
Here's the source code for the shaders:
Vertexshader:
//vertexshader
precision mediump float;
uniform mat4 mPMatrix;
uniform mat4 mVMatrix;
uniform mat4 mMMatrix;
uniform mat4 mMVMatrix;
attribute vec4 aVertex;
attribute vec3 aNormal;
attribute vec2 aTexCoord;
varying vec2 vecTexCoord;
varying vec3 vecNormal;
varying vec4 vecVertex[2];
void main() {
gl_Position = mPMatrix * mMVMatrix * aVertex;
vecVertex[0] = mMMatrix * aVertex;
vecVertex[1] = mMVMatrix * aVertex;
vecTexCoord = aTexCoord;
vecNormal = normalize(vec3(mMMatrix * -vec4(aNormal,0.0)));
}
Fragmentshader:
#define MAX_POINT_LIGHTS 4
precision mediump float;
varying vec2 vecTexCoord;
varying vec3 vecNormal;
varying vec4 vecVertex[2];
uniform vec3 uVecEye;
uniform vec3 uPointLightPosition[MAX_POINT_LIGHTS];
uniform vec3 uPointLightColor[MAX_POINT_LIGHTS];
uniform sampler2D textureHandle;
vec3 V = normalize(uVecEye.xyz-vecVertex[1].xyz);
vec3 N = vNormal;
vec3 vecLight[MAX_POINT_LIGHTS];
vec4 pointDiffuse = vec4(0.0);
vec4 pointSpecular = vec4(0.0);
vec4 ambient = vec4(0.2,0.2,0.2,1.0);
vec4 color = vec4(1.0,1.0,1.0,1.0);
vec4 matSpec = vec4(1.0,1.0,1.0,1.0);
vec4 lightSpec = vec4(1.0,1.0,1.0,1.0);
vec4 spec = matSpec * lightSpec;
float shininess = 20.0;
void main() {
for (int i=0;i<MAX_POINT_LIGHTS;i++) {
vecLight[i].xyz = vecVertex[0].xyz - uPointLightPosition[i].xyz;
float vecDistance = length(vecLight[i].xyz);
if (vecDistance<=25.0) {
vecDistance = 1.0 - max(0.0,vecDistance)/25.0;
vec3 L = normalize(vecLight[i]);
vec3 R = normalize(reflect(L,N));
float LND = max(0.0,dot(N,L)) * vecDistance;
pointDiffuse += color * vec4(uPointLightColor[i].xyz,0.0) * LND;
if (shininess!=0.0 && spec!=0.0) {
pointSpecular += spec * pow(max(0.0,dot(R,V)),shininess) * LND;
} else {
pointSpecular += vec4(0.0,0.0,0.0,0.0);
}
}
}
vec4 colorTexture = texture2D(textureHandle,vec2(+vTexCoord.x,-vTexCoord.y));
gl_FragColor = ambient + colorTexture * pointDiffuse + pointSpecular;
}
Every time I try to run the program, the ShaderlogInfo and ProgramlogInfo say to me:
Invalid fragment shader. Link cannot proceed.*
Am I crazy or just blind?!
I hope you know an answer... I really don't know any... please help me!
The log you got is from the Program linking stage, glGetProgramInfoLog.
What you need to debug is the Fragment Shader log, glGetShaderInfoLog.
Something along these lines:
def _compile(self, source):
ptr = cast(c_char_p(source), POINTER(c_char))
glShaderSource(self.id, 1, byref(ptr), None)
glCompileShader(self.id)
status = c_int(0)
glGetShaderiv(self.id, GL_COMPILE_STATUS, byref(status))
log = self.check()
print(log),
if not status.value:
raise Exception(log)
def check(self):
length = c_int(0)
glGetShaderiv(self.id, GL_INFO_LOG_LENGTH, byref(length))
log = create_string_buffer(length.value)
glGetShaderInfoLog(self.id, length.value, None, log)
return log.value
Though this is not in java but in python, it should give you an idea of how to get your shader compile log.
Compiling your shaders in my environment gives me this log which may or may not be useful to you:
Vertex shader was successfully compiled to run on hardware.
WARNING: 0:2: warning(#260) Keyword 'precision' is supported in GLSL 1.3
Fragment shader failed to compile with the following errors:
WARNING: 0:2: warning(#260) Keyword 'precision' is supported in GLSL 1.3
ERROR: 0:14: error(#143) Undeclared identifier vNormal
WARNING: 0:14: warning(#402) Implicit truncation of vector from size 1 to size 3.
ERROR: 0:50: error(#143) Undeclared identifier vTexCoord
ERROR: 0:50: error(#216) Vector field selection out of range 'y'
ERROR: error(#273) 4 compilation errors. No code generated

Categories

Resources