How can I find the interpolated position between 4 vertices in a fragment shader? - geometry

I'm creating a shader with SharpDX (DirectX11 in C#) that takes a segment (2 points) from the output of a Vertex Shader and then passes them to a Geometry Shader, which converts this line into a rectangle (4 points) and assigns the four corners a texture coordinate.
After that I want a Fragment Shader (which recieves the interpolated position and the interpolated texture coordinates) that checks the depth at the "spine of the rectangle" (that is, in the line that passes through the middle of the rectangle.
The problem is I don't know how to extract the position of the corresponding fragment at the spine of the rectangle. This happens because I have the texture coordinates interpolated, but I don't know how to use them to get the fragment I want, because the coordinate system of a) the texture and b) the position of my fragment in screen space are not the same.
Thanks a lot for any help.

I think it's not possible to extract the position of the corresponding fragment at the spine of rectangle. But for each fragment you have interpolated position (all, what you need to get it is to transmit it to fragment shader, and it will be interpolated for each fragment), and texture coordinates. Why can't you use it? Why do you need to find exactly fragment coordinates?
Also, you can generate some additional data in geometry shader to do what you want.

Related

Using one color to draw a triangle stored inside a buffer opengl es 2.0

I am drawing many different triangles with one draw call glDrawElements.
I am storing the vertices inside a buffer with glBufferData.
I can now give each triangle a different color by storing the color data inside the same buffer i store the vertices. I can then use glVertexAttribPointer to tell opengl where the colors are. Inside the vertex shader i define an attribute and then copy it to a varying in order to pass it to the fragment shader.
This means that I have to define a color for each vertex of the triangle. So i have to define 3 colors, but I only need 1 color for each triangle.
Is there a way to do this more efficient? Does it even matter? Can I store 1 color for each triangle inside a server side buffer?

Inputting Position Into the Pixel Shader

In most of the programs I have seen that make use of vertex position data in the Pixel Shader, there is a tendency to process it as a float4 vector. This restriction does not appear to be present fin the other shaders. In the program that I am currently writing, for instance, float2's are inputted into the VS and float3's into the GS with no problem. But when I try to input this data into the PS, it rejects all forms except for float4. Are other vector types not allowed into the PS? If so, why?
In a pixel shader, the SV_Position is a system-generated value which must be a float4. When you use the SV_Position semantic in a vertex shader, it's basically just an alias for the old POSITION semantic and comes from the Input Assembler in whatever format the Input Layout specifies. The binding between a vertex and geometry shader has to agree, but can be whatever value.
In other words, it has a special meaning for a pixel shader because it's the pixel position as computed by the rasterizer stage.

How can i create an image morpher inside a graphics shader?

Image morphing is mostly a graphic design SFX to adapt one picture into another one using some points decided by the artist, who has to match the eyes some key zones on one portrait with another, and then some kinds of algorithms adapt the entire picture to change from one to another.
I would like to do something a bit similar with a shader, which can load any 2 graphics and automatically choose zones of the most similar colors in the same kinds of zone of the picture and automatically morph two pictures in real time processing. Perhaps a shader based version would be logically alot faster at the task? except I don't even understand how it works at all.
If you know, Please don't worry about a complete reply about the process, it would be great if you have save vague background concepts and keywords, for how to attempt a 2d texture morph in a graphics shader.
There are more morphing methods out there the one you are describing is based on geometry.
morph by interpolation
you have 2 data sets with similar properties (for example 2 images are both 2D) and interpolate between them by some parameter. In case of 2D images you can use linear interpolation if both images are the same resolution or trilinear interpolation if not.
So you just pick corresponding pixels from each images and interpolate the actual color for some parameter t=<0,1>. for the same resolution something like this:
for (y=0;y<img1.height;y++)
for (x=0;x<img1.width;x++)
img.pixel[x][y]=(1.0-t)*img1.pixel[x][y] + t*img2.pixel[x][y];
where img1,img2 are input images and img is the ouptput. Beware the t is float so you need to overtype to avoid integer rounding problems or use scale t=<0,256> and correct the result by bit shift right by 8 bits or by /256 For different sizes you need to bilinear-ly interpolate the corresponding (x,y) position in both of the source images first.
All This can be done very easily in fragment shader. Just bind the img1,img2 to texture units 0,1 pick the texel from them interpolate and output the final color. The bilinear coordinate interpolation is done automatically by GLSL because texture coordinates are normalized to <0,1> no matter the resolution. In Vertex you just pass the texture and vertex coordinates. And in main program side you just draw single Quad covering the final image output...
morph by geometry
You have 2 polygons (or matching points) and interpolate their positions between the 2. For example something like this: Morph a cube to coil. This is suited for vector graphics. you just need to have points corespondency and then the interpolation is similar to #1.
for (i=0;i<points;i++)
{
p(i).x=(1.0-t)*p1.x + t*p2.x
p(i).y=(1.0-t)*p1.y + t*p2.y
}
where p1(i),p2(i) is i-th point from each input geometry set and p(i) is point from the final result...
To enhance visual appearance the linear interpolation is exchanged with specific trajectory (like BEZIER curves) so the morph look more cool. For example see
Path generation for non-intersecting disc movement on a plane
To acomplish this you need to use geometry shader (or maybe even tesselation shader). you would need to pass both polygons as single primitive, then geometry shader should interpolate the actual polygon and pass it to vertex shader.
morph by particle swarms
In this case you find corresponding pixels in source images by matching colors. Then handle each pixel as particle and create its path from position in img1 to img2 with parameter t. It i s the same as #2 but instead polygon areas you got just points. The particle has its color,position you interpolate both ... because there is very slim chance you will get exact color matches and the count ... (histograms would be the same) which is in-probable.
hybrid morphing
It is any combination of #1,#2,#3
I am sure there is more methods for morphing these are just the ones I know of. Also the morphing can be done not only in spatial domain...

What happened in rasterizer stage?

I want to use Direct3D 11 to blend several images that from multi-view into one texture, so i do multiple projection at Vertex Shader stage and Geometry Shader stage, one of the projection's result stored in SV_Position, others stored in POSITION0, POSITION1 and so on. These positions would be used to sample the image.
Then at the Pixel shader stage, the value in SV_Position is typical like a (307.5,87.5), because it's in screen space. as the size of render target is 500x500, so the uv for sample is (0.615,0.0.175), it's correct. but value in POSITION0 would be like a (0.1312, 0.370), it's vertical reversed with offset. i have to do (0.5 + x, 0.5 - y). the projection is twisted and just roughly matched.
What do the rasterizer stage do on SV_Position?
The rasterizer stage expects the coordinates in SV_Position to be normalized device coordinates. In this space X and Y values between -1.0 and +1.0 cover the whole output target, with Y going "up". That way you do not have to care about the exact output resolution in the shaders.
So as you realized, before a pixel is written to the target another transformation is performed. One that inverts the Y axis, scales X and Y and moves the origin to the top left corner.
In Direct3D11 the parameters for this transformation can be controlled through the ID3D11DeviceContext::RSSetViewports method.
If you need pixel coordinates in the pixel shader you have to do the transformation yourself. For accessing the output resolution in the shader bind them as shader-constants, for example.

HLSL Set pixel position in pixel shader to control where the pixel will end up in the texture

How can I manually set where the pixel ends up in the texture in PixelShaderFunction HLSL? Ideally I want the GPU to follow the next logic:
Write pixels one by one in no particular order. Meaning whenever first pixel comes out, write it into the top left corner of the texture. Write second one to the right of the first one and the third one to the right of the first one, and so on.
When you reach the end of the line - go to the next line.
When you reach the end of the texture - drop all the remaining pixels.
Thanks.
I feel like I can do it by manually computing the needed position for my pixel at the vertex shader level. If I could understand better how the pixel positioning works I might be able to pull it out. If I have a render target 2000*4. How can I ensure at the vertex shader level that my pixel will end up in the second row?
What if my RenderTarget is a texture with height = 1 can I not bother computing the positions? Or do I risk loosing data via pixel merging? I am planning to draw nothing but long lines through the screen, one by one and clear the target in between.
Basically you can't do what you're describing.
After the vertex shader, the GPU has a collection of triangles to draw. It fills them, pixel-by-pixel, on the render target (possibly the backbuffer). As part of this filling process - to determine the colour of each pixel - your pixel shader gets called (like a function) for that specific pixel being filled. There is no capacity at this point for "moving" the output pixel.
What you can do is modulate the texture coordinate parameter to tex2D (MSDN) when sampling from a texture in your pixel shader. You can apply whatever functions make sense to achieve your desired result.
Or, if the transform is simple, you can simply set the texture coordinates appropriately either in the vertex data, or using a vertex shader.

Resources