I've just added an uv-scaling feature and I've discovered that the mipmapping is not working as I expected. I pass this scale to the shader which simply multiplies the input texcoord with this value.
However the result is "ziggy" like when I don't have any mipmap. This is because I modified the texture coordinates and the driver don't know which mip level it should choose.
How should I handle this kind of situation?
Related
I have a GLSL shader that draws a 3D curve given a set of Bezier curves (3d coordinates of points). The drawing itself is done as I want except the occlusion does not work correctly, i.e., under certain viewpoints, the curve that is supposed to be in the very front appears to be still occluded, and reverse: the part of a curve that is supposed to be occluded is still visible.
To illustrate, here are couple examples of screenshots:
Colored curve is closer to the camera, so it is rendered correctly here.
Colored curve is supposed to be behind the gray curve, yet it is rendered on top.
I'm new to GLSL and might not know the right term for this kind of effect, but I assume it is occlusion culling (update: it actually indicates the problem with depth buffer, terminology confusion!).
My question is: How do I deal with occlusions when using GLSL shaders?
Do I have to treat them inside the shader program, or somewhere else?
Regarding my code, it's a bit long (plus I use OpenGL wrapper library), but the main steps are:
In the vertex shader, I calculate gl_Position = ModelViewProjectionMatrix * Vertex; and pass further the color info to the geometry shader.
In the geometry shader, I take 4 control points (lines_adjacency) and their corresponding colors and produce a triangle strip that follows a Bezier curve (I use some basic color interpolation between the Bezier segments).
The fragment shader is also simple: gl_FragColor = VertexIn.mColor;.
Regarding the OpenGL settings, I enable GL_DEPTH_TEST, but it does not seem to have anything of what I need. Also if I put any other non-shader geometry on the scene (e.g. quad), the curves are always rendered on the top of it regardless the viewpoint.
Any insights and tips on how to resolve it and why it is happening are appreciated.
Update solution
So, the initial problem, as I learned, was not about finding the culling algorithm, but that I do not handle the calculation of the z-values correctly (see the accepted answer). I also learned that given the right depth buffer set-up, OpenGL handles the occlusions correctly by itself, so I do not need to re-invent the wheel.
I searched through my GLSL program and found that I basically set the z-values as zeros in my geometry shader when translating the vertex coordinates to screen coordinates (vec2( vertex.xy / vertex.w ) * Viewport;). I had fixed it by calculating the z-values (vertex.z/vertex.w) separately and assigned them to the emitted points (gl_Position = vec4( screenCoords[i], zValues[i], 1.0 );). That solved my problem.
Regarding the depth buffer settings, I didn't have to explicitly specify them since the library I use set them up by default correctly as I need.
If you don't use the depth buffer, then the most recently rendered object will be on top always.
You should enable it with glEnable(GL_DEPTH_TEST), set the function to your liking (glDepthFunc(GL_LEQUAL)), and make sure you clear it every frame with everything else (glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)).
Then make sure your vertex shader is properly setting the Z value of the final vertex. It looks like the simplest way for you is to set the "Model" portion of ModelViewProjectionMatrix on the CPU side to have a depth value before it gets passed into the shader.
As long as you're using an orthographic projection matrix, rendering should not be affected (besides making the draw order correct).
I'm trying to code a texture reprojection using a UV gBuffer (this is a texture that contains the UV desired value for mapping at that pixel)
I think that this should be easy to understand just by seeing this picture (I cannot attach due low reputation):
http://www.andvfx.com/wp-content/uploads/2012/12/3-objectes.jpg
The first image (the black/yellow/red/green one) is the UV gBuffer, it represents the uv values, the second one is the diffuse channel and the third the desired result.
Making this on OpenGL is pretty trivial.
Draw a simple rectangle and use as fragmented shader this pseudo-code:
float2 newUV=texture(UVgbufferTex,gl_TexCoord[0]).xy;
float3 finalcolor=texture(DIFFgbufferTex,newUV);
return float4(finalcolor,0);
OpenGL takes care about selecting the mipmap level, the anisotropic filtering etc, meanwhile if I make this on regular CPU process I get a single pixel for finalcolor so my result is crispy.
Any advice here? I was wondering about computing manually a kind of mipmaps and select the level by checking the contiguous pixel but not sure if this is the right way, also I doubt how to deal with that since it could be changing fast on horizontal but slower on vertical or viceversa.
In fact I don't know how this is computed internally on OpenGL/DirectX since I used this kind of code for a long time but never thought about the internals.
You are on the right track.
To select mipmap level or apply anisotropic filtering you need a gradient. That gradient comes naturally in GL (in fragment shaders) because it is computed for all interpolated variables after rasterization. This all becomes quite obvious if you ever try to sample a texture using mipmap filtering in a vertex shader.
You can compute the LOD (lambda) as such:
ρ = max (((du/dx)2 + (dv/dx)2)1/2
, ((du/dy)2 + (dv/dy)2)1/2)
λ = log2 ρ
The texture is picked basing on the size on the screen after reprojection. After you emit a triangle, check the rasterization size and pick the appropriate mipmap.
As for filtering, it's not that hard to implement i.e. bilinear filtering manually.
what am trying to do is getting the Position of the vertex after translation, rotation, scaling, and get the Normal direction, after translation, rotation, scaling , then pass the values to my C++ app , is that possible ?
Possible yes, but the most elegant method depends on the OpenGL version profile available. The most elegant solution would be vertex transform feedback https://www.opengl.org/wiki/Transform_Feedback
If you don't have VTF you'll have to write the information into the framebuffer (in a fragment buffer object) for readback (this will of course prevent you from seeing a "image" but just give you color coded information). Render in GL_POINTS mode, use the gl_VertexID to set the fragment position, pass the transformed data to the fragment shader and have the fragment shader write it into the right color channels.
In WebGL, is it possible to write to the fragment's depth value or control the fragment's depth value in some other way?
As far as I could find, gl_FragDepth is not present in webgl 1.x, but I am wondering if there is any other way (extensions, browser specific support, etc) to do it.
What I want to archive is to have a ray traced object play along with other elements drawn using the usual model, view, projection.
There is the extension EXT_frag_depth
Because it's an extension it might not be available everywhere so you need to check it exists.
var isFragDepthAvailable = gl.getExtension("EXT_frag_depth");
If isFragDepthAvailable is not falsey then you can enable it in your shaders with
#extension GL_EXT_frag_depth : enable
Otherwise you can manipulate gl_Position.z in your vertex shader though I suspect that's not really a viable solution for most needs.
Brad Larson has a clever workaround for this that he uses in Molecules (full blog post):
To work around this, I implemented my own custom depth buffer using a
frame buffer object that was bound to a texture the size of the
screen. For each frame, I first do a rendering pass where the only
value that is output is a color value corresponding to the depth at
that point. In order to handle multiple overlapping objects that might
write to the same fragment, I enable color blending and use the
GL_MIN_EXT blending equation. This means that the color components
used for that fragment (R, G, and B) are the minimum of all the
components that objects have tried to write to that fragment (in my
coordinate system, a depth of 0.0 is near the viewer, and 1.0 is far
away). In order to increase the precision of depth values written to
this texture, I encode depth to color in such a way that as depth
values increase, red fills up first, then green, and finally blue.
This gives me 768 depth levels, which works reasonably well.
EDIT: Just realized WebGL doesn't support min blending, so not very useful. Sorry.
I need to render an object using an existing texture, and I need to alter the color during the rendering. (Such as multiplying red channel by 0.5.) The existing texture is not monochromatic. I need to do this without enabling lighting and without shaders so I don't disturb the application I'm working within. I cannot work early enough in the rendering that I could read/write the buffer directly.
In effect, I'd like some sort of color-transformation matrix or filter that works during normal rendering.
Base in the limited information I'll assume some things.
I'll assume you are working with fixed pipeline.
I'll assume you are not using a low level pixel function like glBitmap or glDrawPixels. If you are you should not.
To solve you problem try the following:
Draw a textured quad, using glBegin,glEnd,glVertex2f,glTexCoord2f
To alter the color use glColor just after glBegin and before any other draw instruction.
You should do your color-transformation matrix in the cpu and use that result with glColor.
Image will be blended accordingly. WHITE doesn't change the image color.
Make sure GL_LIGHTING is not enabled.
OpenGL has a color transformation matrix (GL_COLOR) that can be accessed and modified just like GL_MODELVIEW or GL_PROJECTION (you will most probably need glLoadMatrix or glMultMatrix, as glRotate and such doesn't make much sense with colors). It requires the extension GL_ARB_imaging.