How do I use an OpenGL shader to modify an existing texture / frame buffer in place without using a second texture or frame buffer? Is this even possible?
At first:
It is technically possible and safe to read and write in the same pass using this extension - however i wouldn't recommend this, especially for learners, since the extension is tightly limited and might not be supported on every hardware.
That being said:
So it's not possible to use the same texture as a sampler and frame buffer?
You can use the same texture as a framebuffer texture attachment and render to it and as a texture sampler to look up values in the shader, but not in the same pass. That means, if you have two textures you could read from A and write to B and afterwards switch textures and read from B and write to A. But never A->A or B->B (without the extension mentioned).
As a technical detail, a texture currently being used as a target can also be bound to a sampler shader variable at the same time, but you must not use it.
So let's say I want to blur just a small part of a texture. I have to run it through a shader to a second texture and then copy that texture back to the first texture / frame buffer?
Second texture yes. But for efficiency reasons do not copy the texture data back. Just delete the source texture and use the target texture you have rendered to in the future. If you have to do this often, keep the source texture as a render target for later use to increase performance. If you have to do it every frame just swap the textures every frame. The overhead is minimal.
It's tricky to make it using the following code.
// in fragment shader
uniform sampler2D input;
out vec4 color;// bind sampler and framebuffer with same texture
void main(){
ivec2 pos = ivec2(gl_FragCoord.xy);
if(cond){
color = vec4(0.0);
}else{
color = texelFetch(input, pos, 0);
}
}
Related
In my 2D map application, I have 16-bit heightmap textures containing altitudes in meters associated to a point on the map.
When I draw these textures on the screen, I would like to display an analysis such that the pixel referring to the highest altitude on the screen is white, the pixel referring to the lowest altitude in the screen is black and the values in-between are interpolated between those two.
I'm using an older OpenGL version and thus do not have access to modern pipeline functionality like GLSL or PBO (Which somehow can make getting color buffer contents to CPU side much more efficient than glReadPixels, as I've heard).
I have access to ATI_fragment_shader extension which makes possible to use a basic fragment shader to merge R and G channels in these textures and get a single float grayscale luminance value.
Then I would've been able to re-color these pixels again inside shader (Map them to 0-1 range) based on maximum and minimum pixel luminance values but I don't know what they are.
My question is, between the pixels currently on the screen, how do I find the pixels with maximum and minimum luminance values? Or as an alternative, how do I find these values inside a texture? (Because I could make a glCopyTexImage2D call after drawing the texture with grayscale luminance values on the screen and retrieve the data as a texture).
Stuff I've tried or read about so far:
-If I could somehow get current pixel RGB values in the color buffer to CPU side, I could find what I need manually and then use them. However, reading color buffer contents with glReadPixels is unacceptably slow. It's no use even if I set it up so that it completes one read operation over multiple frames.
-Downsampling the texture to 1x1 size until the last standing pixel is either minimum or maximum value and then using this 1x1 texture inside shader. I have no idea how to achieve this without GLSL and texel fetching support since I would have to look up the pixel which is to the right, up and up-right of the current one and find a min/max value between them.
From my own trial-and-error experience, it seems that DirectX pixel shaders only run for pixels/fragments that are within the bounds of some geometric primitive rendered by DirectX, and are not run for pixels of the frame that are simply the clear-color.
MSDN says:
Pixel shaders work in concert with vertex shaders; the output of a vertex shader provides the inputs for a pixel shader.
This stands in contrast to WPF pixel shaders, which are run for every pixel of the frame, because WPF doesn't render 3D primitives and therefore doesn't know or care what it means to be a geometric primitive pixel or clear-color pixel.
So for the following image, a DirectX pixel shader would only be run for the area in white, because it corresponds to a geometric primitive output by the vertex shader, but not for the black area, because that's the clear-color. A WPF pixel shader, on the other hand, would be run for every pixel of the frame, both white and black.
Is this understanding correct?
Your understanding is mostly correct - pixel shader invocations are triggered by drawing primitives (e.g. triangles). In fact, a pixel in the window may end up getting more than one pixel shader invocation, if for example a second triangle is drawn on top of the first. This is referred to as overdraw and is generally something to avoid, with the most common method of avoidance being using z-culling.
If you want to trigger a pixel shader for every pixel in the window, simply draw two triangles that make up a "full screen quad", i.e. coordinates (-1,-1) to (1,1). Behind the scenes, this is what WPF essentially does.
I want to add characters (x/y/z.., not even strings) to a window using OpenGL, WITHOUT using GLUT. I know about glutBitmapString(), but I want to avoid glut. Any suggestions...?
Last time I did this for a retro-style game, I created a bitmap font and wrote a small routine that would draw a quad with the specific character as a texture on it. Another option is to draw every pixel of the bitmap font in a seperate quad.
You can find example code here:
http://svn.berlios.de/wsvn/pong2/trunk/src/Interface.h
http://svn.berlios.de/wsvn/pong2/trunk/src/Interface.cpp
More specifically:
void Interface::createFont() initiates a bitmap font as a display list for each character
void Interface::drawText(const std::string& text) lets OpenGL call the display lists according to the string's characters
In this specific example, I wanted textured "pixels" within the characters, so each bitmap entry results in its own quad with a stock texture on it. Display lists are nowadays less favored as newer OpenGL features like FBOs and VBOs replace their functionality. I don't know if at some point display lists got deprecated as well.
The text in createFont() was created by The Gimp (http://www.gimp.org) export functionality.
Screenshot to celebrate the 20k:
I would suggest using a glyph map, which basically boils down to a bitmap texture with a bunch of letters distributed over it. Load in the texture and draw quads with texture coordinates mapped to the location of the glyph you want in the texture.
There are some drawbacks in a naive implementation that can be partially alleviated. For example, rather than drawing a ton of quads in separate draw calls, you could take a cue from Java and make immutable strings that tie to a GPU buffer and pack all the vertices and uvs you need to draw the word into that buffer. (They don't have to be immutable, just know that if you need to make a word longer or shorter, you'll have to reallocate the buffer or leave extra space to put the new letters).
The site that I used whenever I was trying to learn how to do this can be found here:
Bitmap Fonts
I have used this method with a WebGL implementation and it has worked quite well. I even have wrote a tool to generate the texture from a <canvas> element on the fly.
How can I load an image in openGL? How can I transfer the image data to the data that openGL can understand?
I'll break it into steps:
Read the file contents into memory
Decode the file to raw format required (RGB or RGBA)
Create OpenGL texture object and give the raw image data to OpenGL
Construct OpenGL primitive with appropriate texture coordinates and vertices positions.
Bind the texture to appropriate texture unit and use a sampler object to use the texture data to produce final color.
6. Profit!
Step 1, 2 and 3 can be easily changed to simple SOIL_load_texture call, if you want to use SOIL image library.
First you have to decode the image into an RGBA-array. See here:
https://en.wikipedia.org/wiki/libpng
Then you have to map it to an OpenGL-texture and display:
http://nehe.gamedev.net/tutorial/texture_mapping/12038/
In WPF, I want to use a pixel shader to modify a composite image i.e. a new image overlaid on top of a previously shaded image. The new image comes in as a largely transparent image except where there is data (think mathematical functions - sine wave, etc). Anyway this process needs to repeat pretty rapidly - compose the currently shaded texture with a new image and then shade the composite image. The problem is that I don't know how to access the previously shaded texture from within my shader.
Basically, you need to add a Texture2D variable in your shader, then set that parameter as the texture you need to access before drawing the new one (i'm unsure of that process in WPF). You do something like this:
//blahblahblah variables here
Texture2D PreviousTexture;
Sampler PreviousTextureSampler = Sampler2D { Texture = PreviousTexture; };
//blahblahblah code here
then you can sample the texture with a tex2D call.