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 );
Related
I am trying to pass a texture to my shader, but when the sampler2D uniform I am setting to my texture has same content as the u_sampler2D holding the current texture provided by OpenGL.
Here is how I set the uniform (this is in my SpriteBatch's begin method before calling super.begin()):
texture.bind();
this.getShader().begin();
this.getShader().setUniformi("u_LightMap",0);
this.getShader().setUniformf("u_camOffset", new Vector3(inputMethod.getCameraOffsetX(), inputMethod.getCameraOffsetY(), inputMethod.getZoom()));
this.getShader().end();
This is my testing shader:
precision mediump float;
varying vec4 v_color;
varying vec2 v_texCoord0;
uniform vec4 gl_FragCoord;
uniform sampler2D u_sampler2D;
uniform sampler2D u_LightMap;
uniform vec3 u_cam;
uniform vec2 resolution;
void main () {
vec4 lightColor = texture2D(u_LightMap, gl_FragCoord);
gl_FragColor = lightColor;
}
Where is the problem? ~BeefEX
Look at the source code you're calling in super.begin(). It's binding the texture of the sprites to the same unit you just bound your other texture to, overwriting it. Bind your custom texture to unit one, and then change the GL active texture unit back to 0 before calling super.
I am trying to create a GLSL texture shader in java on a mac, but mac doesn't support any version above #version 120. How would I port this 330 shader:
//this is my Vertex Shader
#version 330
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;
out vec2 texCoord0;
uniform mat4 transform;
void main()
{
gl_Position=transform*vec4(position,1.0);
texCoord0=texCoord;
}
This is my Fragment Shader
#version 330
in vec2 texCoord0;
uniform sampler2D sampler;
out vec4 gl_FragColor;
void main()
{
gl_FragColor=texture2D(sampler,texCoord0.xy);
}
How do I convert these shaders to glsl 120 without losing functionality?
You just have to:
_Remove the layout qualifiers (including location assignment). You'll the have to use
void glBindAttribLocation(GLuint program,
GLuint index,
const GLchar *name);
for each input of your vertex shader (with index set to 0 and 1 for location 0 and 1 and the name of the variable in case you didn't understand) before linking your program
_In the vertex shader, replace in by attribute and out by varying
_In the fragment shader, replace in by varying and use gl_FragColor but without declaring it
In your case, you would have this just before linking your program:
//program is your shader program of course...
//Bind vertex shader attributes (ins) instead of using layout
glBindAttribLocation(program, 0, "position");
glBindAttribLocation(program, 1, "texCoord");
//Then the program should be linked (or relinked, it doesn't matter)
glLinkProgram(program);
Your vertex shader:
#version 120
attribute vec3 position;
attribute vec2 texCoord;
varying vec2 texCoord0;
uniform mat4 transform;
void main()
{
gl_Position = transform*vec4(position, 1.0);
texCoord0 = texCoord;
}
And your fragment shader:
#version 120
varying vec2 texCoord0;
uniform sampler2D sampler;
void main()
{
gl_FragColor = texture2D(sampler, texCoord0.xy);
}
In libgdx, I have a shader loaded, and I want to make my Stage object use that shader to draw. I tried setting a SpriteBatch's shader to my shader, and then the Stage's sprite batch to that one, but it shows up as a black screen. Why doesn't this work:
ShaderProgram shader = new ShaderProgram(Gdx.files.internal("shader.vert"), Gdx.files.internal("shader.frag"));
SpriteBatch batch = new SpriteBatch();
batch.setShader(shader);
Stage stage = new Stage(new StretchViewport(768, 576), batch);
...
stage.act();
shader.begin();
stage.draw();
shader.end();
My shaders look like:
shader.vert
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord;
uniform mat4 u_projTrans;
varying vec4 v_color;
varying vec2 v_texCoords;
void main()
{
v_color = a_color;
v_color.a = v_color.a * (256.0/255.0);
v_texCoords = a_texCoord + 0;
gl_Position = u_projTrans * a_position;
}
shader.frag
#ifdef GL_ES
#define LOWP lowp
precision mediump float;
#else
#define LOWP
#endif
varying LOWP vec4 v_color;
varying vec2 v_texCoords;
uniform sampler2D u_texture;
void main()
{
gl_FragColor = v_color * texture2D(u_texture, v_texCoords);
}
It seems to only work with one texture. Every other texture doesn't render. And also, making textures power of 2 doesn't make a difference.
SpriteBatch has certain expected attribute names. You are using a_texCoord, but it expects a_texCoord0, so the shader is going to treat all the UV's as if they are 0,0.
You mention setting the shader on both the SpriteBatch and the Stage's SpriteBatch, but in your code, they are one and the same.
You don't need to call begin and end on the shader, because SpriteBatch (and therefore Stage) does this automatically. I'm not sure if that could cause problems.
I can't explain why what you did would have worked with one of your textures. I would expect it to just draw everything as the same color as the lower left pixel of the texture.
There might be other issues afoot, but I'm assuming it was drawing correctly before you inserted your own shader.
I'm trying to understand shaders using libgdx, coming from an XNA/HLSL background. I'm trying to get a vert/frag shader pair to reproduce the output I get without a shader, but it's not displaying anything.
Shader creation:
void SetupShader()
{
ShaderProgram.pedantic = false;
shader = new ShaderProgram(
Gdx.files.internal("assets/default.vert").readString(),
Gdx.files.internal("assets/default.frag").readString());
if(!shader.isCompiled()) {
Gdx.app.log("Problem loading shader:", shader.getLog());
}
batch.setShader(shader);
}
default.vert:
attribute vec4 a_Position;
attribute vec4 a_Normal;
attribute vec2 a_TexCoord;
attribute vec4 a_Color;
uniform mat4 u_projTrans;
varying vec2 v_texCoords;
varying vec4 v_color;
void main() {
v_color = a_Color;
v_texCoords = a_TexCoord;
gl_Position = u_projTrans * a_Position;
}
default.frag:
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoords;
varying vec4 v_color;
void main() {
gl_FragColor = v_color;
}
Rendering:
batch.begin();
for (GameObject gObj : gameObjects)
gObj.Draw(batch);
batch.end();
Any suggestions here? I'm new to OpenGL-ES as well, so I may be missing something obvious. I looked around a bit before posting, and the doc for SpriteBatch.setShader(ShaderProgram) was as follows:
Sets the shader to be used in a GLES 2.0 environment. Vertex position
attribute is called "a_position", the texture coordinates attribute is
called called "a_texCoords0", the color attribute is called "a_color".
See ShaderProgram.POSITION_ATTRIBUTE, ShaderProgram.COLOR_ATTRIBUTE
and ShaderProgram.TEXCOORD_ATTRIBUTE which gets "0" appened to
indicate the use of the first texture unit. The projection matrix is
uploaded via a mat4 uniform called "u_proj", the transform matrix is
uploaded via a uniform called "u_trans", the combined transform and
projection matrx is is uploaded via a mat4 uniform called
"u_projTrans". The texture sampler is passed via a uniform called
"u_texture". Call this method with a null argument to use the default
shader.
After looking at the code in SpriteBatch it seems that I had a few mistakes in my code. Below are the correct shaders:
default.vert:
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord0;
uniform mat4 u_projTrans;
varying vec4 v_color;
varying vec2 v_texCoords;
void main() {
v_color = a_color;
v_texCoords = a_texCoord0;
gl_Position = u_projTrans * a_position;
}
default.frag:
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_color;
varying vec2 v_texCoords;
uniform sampler2D u_texture;
void main() {
gl_FragColor = v_color * texture2D(u_texture, v_texCoords);
}
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