I've been struggling with the shadow mapping for two days (with JOGL), yet still couldn't make it work. Now I just want to render a very simple shadow map (grass), where closer looks brighter and further looks darker, from the view of the light point.
Here is my code:
//setting up buffers
gl.glGenFramebuffers(1, framebuff);
gl.glBindFramebuffer(GL4.GL_FRAMEBUFFER, framebuff.get(0));
gl.glGenTextures(2, textureBuff);
gl.glBindTexture(GL4.GL_TEXTURE_2D, textureBuff.get(0));
gl.glTexStorage2D(GL4.GL_TEXTURE_2D, 1, GL4.GL_R32F, displayWidth, displayHeight);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MAG_FILTER, GL4.GL_LINEAR);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MIN_FILTER, GL4.GL_LINEAR_MIPMAP_LINEAR);
gl.glFramebufferTexture(GL4.GL_FRAMEBUFFER, GL4.GL_COLOR_ATTACHMENT0, textureBuff.get(0), 0);
gl.glBindTexture(GL4.GL_TEXTURE_2D, textureBuff.get(1));
gl.glTexStorage2D(GL4.GL_TEXTURE_2D, 1, GL4.GL_DEPTH_COMPONENT32F, displayWidth, displayHeight);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MAG_FILTER, GL4.GL_LINEAR);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MIN_FILTER, GL4.GL_LINEAR_MIPMAP_LINEAR);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_COMPARE_MODE, GL4.GL_COMPARE_REF_TO_TEXTURE);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_COMPARE_FUNC, GL4.GL_LEQUAL);
gl.glFramebufferTexture(GL4.GL_FRAMEBUFFER, GL4.GL_DEPTH_ATTACHMENT, textureBuff.get(1), 0);
gl.glDrawBuffer(GL4.GL_NONE);
if(gl.glCheckFramebufferStatus(GL4.GL_FRAMEBUFFER) != GL4.GL_FRAMEBUFFER_COMPLETE)
System.out.println(gl.glCheckFramebufferStatus(GL4.GL_FRAMEBUFFER));
Vertex shader:
"#version 430 \n" +
"layout (location = 3) uniform mat4 mvMatrix; \n" +
"layout (location = 4) uniform mat4 proMatrix; \n" +
"layout (location = 0) in vec4 position; \n" +
" \n" +
"void main(void) \n" +
"{ \n" +
" randomize position... \n" +
" \n" +
" gl_Position = proMatrix * mvMatrix * position; \n" +
"}"
Fragment shader code:
"#version 430 \n" +
"out vec4 output_color; \n" +
"void main(void) \n" +
"{ \n" +
" output_color = vec4(gl_FragCoord.z); \n" +
"}"
drawing command (not sure if it's correct):
//gl.glBindFramebuffer(GL4.GL_FRAMEBUFFER, framebuff.get(0));
gl.glViewport(0, 0, displayWidth, displayWidth);
gl.glEnable(GL4.GL_POLYGON_OFFSET_FILL);
gl.glPolygonOffset(2.0f, 4.0f);
/*IntBuffer frameType = GLBuffers.newDirectIntBuffer(1);
frameType.put(GL4.GL_COLOR_ATTACHMENT0);
gl.glDrawBuffers(1, frameType);
gl.glClearBufferfv(GL4.GL_COLOR, 0, new float[] {0, 0, 0}, 0);
gl.glClearDepth(1.0f);*/
setupMVPMatrix();
gl.glBindVertexArray(vaoBuff.get(0));
gl.glUseProgram(shaderProgram);
gl.glDrawArraysInstanced(GL4.GL_TRIANGLE_STRIP, 0, 5, 512 * 512);
gl.glDisable(GL4.GL_POLYGON_OFFSET_FILL);
//gl.glBindFramebuffer(GL4.GL_FRAMEBUFFER, 0);
added:
when I comment the glBindFramebuffer(), the grass appears correctly with the white color (from the light point of view, which shows the matrix should be correct).
But if I call glBindFramebuffer() with depth test enabled, everything just disappeared while I expect the closer grass to be brighter and further grass to be darker.(also checked the framebuffer status, nothing wrong)
Any help?
Fixed, I didn't understand the meaning of off-screen rendering at the beginning. Just render the depth value stored in the texture into the default framebuffer for display, and everything work just fine. I can't believe I spent 5 days on this.
gl.glBindFramebuffer(GL4.GL_FRAMEBUFFER, framebuff.get(0));
draw scene...(storing the depth value into the depth texture)
gl.glBindFramebuffer(GL4.GL_FRAMEBUFFER, 0);
draw scene...(comparing with the depth texture stored)
Related
I would like to read with glReadPixels() the value from the colorbuffer, which I previously wrote in the Fragmentshader via gl_FragColor. This works on average 10 times, then an erroneous value (1 = 255) occurs.
#version 420
uniform vec2 screenXy;
uniform vec2 screenSize;
out highp vec4 fragColor;
void main(void) {
if((int(gl_FragCoord.x) == int(screenXy.x)) && ((int(screenSize.y - 1) - int(gl_FragCoord.y)) == int(screenXy.y))) {
fragColor.r = 0.5; // any value
} else {
fragColor = vec4(1, 1, 1, 1.0);
}
I submit the mouse xy coordinates to the fragementshader (screenXy). If the clicked pixel is in the row, I write a value (e.g 0.5) in the color buffer. Now I observe that sometimes the value is 1 (= 255) instead of 0.5 (=128).
GLfloat zc[4]; // from color buffer
m_func->glReadPixels(xy.x(), (m_pFbo->height() - 1) - xy.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, z);
qDebug() << "z0 " << z[0];
I see this behavior on win10 and android.
Does anyone has an idea what i'm doing wrong?
I'm trying to draw a stipple pattern using a shader, like as in glStipple. However it does not seem to be working as expected.
The idea is to compare pixel coordinates against a stipple mask and discard fragments if the pixel coordinate mod mask size is 0.
However, two odd things are occurring which suggests the approach has some flaw I'm missing. The first is that the resulting stipple pattern does not match the mask. A single diagonal line in an 8x8 mask results in what appears to be diagonals spaced 1 pixel apart in the drawn shape. The second is that testing against 1, instead of 0, does not give a similar (but shifted) pattern.
The vertex shader looks like this:
static const char *vertexShaderSource =
"attribute highp vec4 posAttr;\n"
"attribute highp vec4 colAttr;\n"
"varying lowp vec4 col;\n"
"varying highp vec2 coord;\n"
"uniform highp mat4 matrix;\n"
"void main() {\n"
" col = colAttr;\n"
" gl_Position = matrix * posAttr;\n"
" coord = gl_Position.xy;\n"
"}\n";
and the fragment shader:
static const char *fragmentShaderSource =
"varying lowp vec4 col;\n"
"varying highp vec2 coord;\n"
"uniform int stipple[64];\n"
"uniform int width;\n"
"uniform int height;\n"
"void main() {\n"
" if (stipple[abs(mod(coord.x * width,8)) + abs(mod(coord.y * height,8)) * 8] == 1)\n"
" {\n"
" discard;\n"
" }\n"
" gl_FragColor = col;\n"
"}\n";
where width and height are the w/h of the viewport and the stipple is e.g.
GLint stipple[64] = {
0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0
};
Any ideas appreciated, thanks.
You can use gl_FragCoord. It contains the pixel's center coordinate. So for a resolution of 800x600 then gl_FragCoord would be in the range of vec2(0.5, 0.5) and vec2(799.5, 599.5). Thereby there's no need to multiply by the resolution, since we already basically have window coordinates.
Since gl_FragCoord wouldn't result in a negative number you can remove abs().
All in all with the few modifications, the fragment shader ends up looking like this:
varying vec4 color;
uniform int stipple[64];
void main()
{
ivec2 coord = ivec2(gl_FragCoord.xy - 0.5);
if (stipple[int(mod(coord.x, 8) + mod(coord.y, 8) * 8)] == 0)
discard;
gl_FragColor = color;
}
Im having trouble with getting a proper location of my uniform in my opengl shaders. I always but always get -1 returned from the glGetUniformLocation Function.
maybe I didnt load it well?
I read online that uniforms can get optimized out for not-using them, but I do use my uniforms in a way that can affect my shaders(or do I,I think I do).
also, everytime I encounter an answer that is related to this problem on stackoverflow or on some other site,they do talk about this fact, but NO ONE EXPLAINS about an alternative solution for this, and that realy got me struggling. is it something new just for new opengl iterations?
here is my vertex shader code:
#version 410 core
in vec4 position;
uniform mat4 mvmatrix;
uniform mat4 projmatrix;
void main(void)
{
gl_Position = projmatrix * mvmatrix * position;
}
here is my fragment shader code:
#version 410 core
out vec4 color;
void main(void)
{
color = vec4(1.0,1.0,1.0,1.0)
}
and here is the whole source code for the whole program..for now I didnt implement the whole code itself,only the part that compliles the program and shaders, but yet, Im struggling to get the location for the uniforms, Ive been struggling with this for several days...hoping someone could save me here:
codeHere
also if you need only the specific part that Im talking about:
//creating program and shaders, compiling shaders, compiling program
GLchar * v_Shader[] = {
"#version 410 core \n"
" \n"
"in vec4 position; \n"
" \n"
" \n"
"uniform mat4 mvmatrix; \n"
"uniform mat4 projmatrix; \n"
" \n"
"void main(void) \n"
"{ \n"
" gl_Position = proj_matrix * mv_matrix * position; \n"
"} \n"
};
GLchar * f_Shader[] = {
"#version 410 core \n"
" \n"
"out vec4 color; \n"
" \n"
"in VS_OUT \n"
"{ \n"
" vec4 color; \n"
"} fs_in; \n"
" \n"
"void main(void) \n"
"{ \n"
" color = vec4(1.0,1.0,1.0,1.0) \n"
"} \n"
};
//creating a opengl program
program = glCreateProgram();
//creating the vertex shader and compiling it
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, v_Shader, NULL);
glCompileShader(vertexShader);
//creating the fragment shader and compiling it
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, f_Shader, NULL);
glCompileShader(fragmentShader);
//attaching the shaders to the program and linking the program
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
glUseProgram(program);
//getting the program's uniform locations
modelViewMatrixLocation = glGetUniformLocation(program, "mvmatrix");
projectionMatrixLocation = glGetUniformLocation(program, "projmatrix");
And nope, I dont like using glfw/sdl/glew/freeglut or any other library. they just confuse me all around.
You are misspelling the uniform names in the vertex shader:
uniform mat4 mvmatrix;
uniform mat4 projmatrix;
...
gl_Position = proj_matrix * mv_matrix * position;
To fix, replace gl_Position line with
gl_Position = projmatrix * mvmatrix * position;
To catch errors like this in the future, check the shader compile status:
GLint wasCompiled;
glGetShaderiv( shader, GL_COMPILE_STATUS, &wasCompiled );
GLint logLength;
glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logLength );
if (logLength > 0)
{
GLchar* log = new GLchar[ (std::size_t)logLength + 1 ];
GLsizei charsWritten = 0;
glGetShaderInfoLog( shader, logLength, &charsWritten, log );
std::cout << std::string( log );
}
You also have a syntax error in your fragment shader:
color = vec4(1.0,1.0,1.0,1.0)
It's missing ; at the end. You should check for shader compile errors.
Your fragment shader takes color as input from vertex shader, but vertex shader doesn't output it and you don't use color input in the fragment shader. To fix, remove these lines:
"in VS_OUT \n"
"{ \n"
" vec4 color; \n"
"} fs_in; \n"
In the latest version in the comments you have a line:
color = vec4(1.0,0.0,0.0.1.0)
There are 2 errors. You are missing ; and the character before 1.0 should be ,, not .
in my Libgdx Scene2D stage I am trying to have an actor flashing with white color.
With OpenGLES 2.0 I understood I needed to use a shader to achieve this and I have a problem implementing it.
My goal is to color an actor in solid white color given a speficic game event. The problem is given this specific event, everything in the stage becomes white (all actors and the background) instead of just the selected actors textures.
My World class is where the stage is created. It is rendered like this:
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
update();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
In the stage I use actors that are defined in a MyActor class. This class has its own
draw method where I am trying to color the actor in solid white with the shader. Here is the draw method:
public void draw(Batch batch, float alpha) {
if (flashing) {
batch.setShader(shader);
}
batch.flush();
Color color = getColor();
batch.setColor(color.r, color.g, color.b, color.a * alpha);
batch.draw(tr, getX(), getY(), side/2, side/2, side, side, getScaleX(), getScaleY(), 0);
}
Obviously I do something wrong with the batch. Instead of coloring this one actor in white, it colors everything. Also it remains white even after the Boolean flashing = false;
Here is how I have set up my shader, in the actor class MyActor:
ShaderProgram shader;
String vertexShader =
"attribute vec4 a_position; \n" +
"attribute vec4 a_color;\n" +
"attribute vec2 a_texCoord0; \n" +
"uniform mat4 u_projTrans; \n" +
"varying vec4 v_color; \n" +
"varying vec2 v_texCoords; \n" +
"void main() { \n" +
"v_color = a_color; \n" +
"v_texCoords = a_texCoord0; \n" +
"gl_Position = u_projTrans * a_position; \n" +
"};";
String fragmentShader = "#ifdef GL_ES\n" +
"precision mediump float;\n" +
"#endif\n" + "varying vec4 v_color;\n" +
"varying vec2 v_texCoords;\n" +
"uniform sampler2D u_texture;\n" +
"uniform float grayscale;\n" +
"void main()\n" +
"{\n" +
"vec4 texColor = texture2D(u_texture, v_texCoords);\n" +
"float gray = dot(texColor.rgb, vec3(5, 5, 5));\n" +
"texColor.rgb = mix(vec3(gray), texColor.rgb, grayscale);\n" +
" gl_FragColor = v_color * texColor;\n" +
"}";
Then initiated with:
shader = new ShaderProgram(vertexShader, fragmentShader);
What is it that I am doing wrong?
I have to admit I probably don't understand correctly how the batch of MyActor, the drawing method and the rendering methods work together!
Thanks for your time
The problem here is, that you never set the Shader back to the default Shader, so your Spritebatch always uses the "solid white" Shader.
As the javadock of the setShader(ShaderProgram shader)sais you can reset the Shader by calling setShader(null).
Another possibility would be to use another Texture for the solid white and the simply say:
Texture t = flashing ? whiteTexture : defaultTexture;
and draw the Texture t.
Just a suggestion: Do not use batch.flush() if it is not absolutely neccessary, because flush() makes a draw call to the GPU and this costs some performance.
I'm a bit confused about how the shader pipeline works with regards to passing data through each stage.
What I'm trying to do is pass color data that is loaded in the vertex stage using glVertexAttrib4fv() through the tessellation control shader, and then the tessellation evaluation shader, so that it can be used in the fragment shader. I'm not sure if I've made some sort of conceptual mistake (quite possible, since I'm still trying to get my head around this over fixed functions), but either way, as soon as I try and pass anything through the tessellation shaders, my primitives refuse to render at all. Before that, my primitive renders, but it only renders in black. My shaders are as follows:
Vertex Shader:
static const GLchar* vss[] =
{
"#version 430 core \n"
" \n"
"layout (location = 0) in vec4 offset; \n"
"layout (location = 1) in vec4 color; \n"
" \n"
"out vec4 vs_color; \n"
" \n"
"void main(void) \n"
"{ \n"
" const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, -0.5, 1.0), \n"
" vec4(-0.25, -0.25, -0.5, 1.0), \n"
" vec4( 0.25, 0.25, -0.5, 1.0)); \n"
" \n"
" gl_Position = vertices[gl_VertexID] + offset; \n"
" vs_color = color; \n"
"} \n"
};
Tessellation control shader:
static const GLchar* tc_ss[] =
{
"#version 430 core \n"
"layout (vertices = 3) out; \n"
"in vec4 vs_color; \n"
"out vec4 tcs_color; \n"
"void main(void) \n"
"{ \n"
" if (gl_InvocationID == 0) \n"
" { \n"
" gl_TessLevelInner[0] = 10.0; \n"
" gl_TessLevelOuter[0] = 10.0; \n"
" gl_TessLevelOuter[1] = 10.0; \n"
" gl_TessLevelOuter[2] = 10.0; \n"
" } \n"
" gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; \n"
" tcs_color = vs_color; \n"
"}"
};
Tessellation Evaluation shader:
static const GLchar* te_ss[] =
{
"#version 430 core \n"
"in vec4 tcs_color; \n"
"out vec4 tes_color; \n"
"layout (triangles, equal_spacing, cw) in; \n"
"void main(void) \n"
"{ \n"
" gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position + \n"
" gl_TessCoord.y * gl_in[1].gl_Position + \n"
" gl_TessCoord.z * gl_in[2].gl_Position); \n"
" tes_color = tcs_color; \n"
"}"
};
Fragment shader:
static const GLchar* fss[] =
{
"#version 430 core \n"
"in vec4 tes_color; \n"
"out vec4 color; \n"
" \n"
"void main(void) \n"
"{ \n"
" color = tes_color; \n"
"} \n"
};
This is not surprising, TCS inputs/outputs must be in the form:
in vec4 vs_color [];
out vec4 tcs_color [];
or in input/output blocks that also take the form of unbounded arrays:
in CustomVertex {
vec4 color;
} custom_vs [];
out CustomVertex {
vec4 color;
} custom_tcs [];
For a little bit of context, this is what a TCS / geometry shader sees as the output from vertex shaders:
in gl_PerVertex
{
vec4 gl_Position;
float gl_PointSize;
float gl_ClipDistance [];
} gl_in [];
To keep things as simple as possible, I will avoid using interface blocks.
Instead, I will introduce the concept of per-patch inputs and outputs, because they will further simplify your shaders considering the color is constant across the entire tessellated surface...
Modified Tessellation Control Shader:
in vec4 vs_color [];
patch out vec4 patch_color;
...
patch_color = vs_color [gl_InvocationID];
Modified Tessellation Evaluation Shader:
patch in vec4 patch_color;
out vec4 tes_color;
...
tes_color = patch_color;
With these changes, you should have a working pass-through and a slightly better understanding of how the TCS and TES stages work.