Problem drawing a rectangle in Godot fragment shader - fragment-shader

I'm having a fragment shader that draw some stuff. On top of that I want it to draw 1-pixel thick rectangle around the fragment. I have using step function, but the problem is the UV coordinates that is between 0.0 -1.0. How do I know when the fragment is at a specific pixel? For this I want to draw on the edges.
c.r = step(0.99, UV.x);
c.r += step(0.99, 1.0-UV.x);
c.r += step(0.99, UV.y);
c.r += step(0.99, 1.0-UV.y);
The code above just draw a rectangle, but the problem thicknes is 0.01% of total width/hight.
Is there any good description of UX, FRAGCOORD, SCREEN_TEXTURE and SCREEN_UV?

If it is good enough for you to work in screen coordinates (i.e., you want to define position and thickness in terms of screen space) you can use FRAGCOORD. It corresponds to the (x, y) pixel coordinates within the viewport, i.e., with the default viewport of 1024 x 600, the lower left pixel would be (0, 0), and the top right would be (1024, 600).
If you want to map the fragment coordinates back to world space (i.e., you want to define position and thickness in terms of world space), you must follow the work-around mentioned here.

Related

How does PDF line width interact with the CTM in both horizontal and vertical dimensions?

I'm trying to figure out exactly how line width affects a stroked line in PDF, given the current transformation matrix (CTM). Two questions...
First: how do I convert the line width to device space using the CTM? Page 208 in the PDF 1.7 Reference, which describes how to convert points using the CTM, assumes the input data is an (x, y) point. Line width is just a single value, so how do I convert it? Do I create a "dummy" point from it like (lineWidth, lineWidth)?
Second: once I make that calculation, I'll get another (x, y) point. If the CTM has different scaling factors for horizontal vs. vertical, that gives me two different line widths. How are these line widths actually applied? Does the first one (x) get applied only when drawing horizontal lines?
A concrete example for the second question: if I draw/stroke a horizontal line from (0, 0) to (4, 4) with line width (2, 1), what are the coordinates of the bounding box of the resulting rectangle (i.e., the rectangle that contains the line width)?
This is from Page 215 in the Reference, but it doesn't actually explain how the thickness of stroked lines will vary:
The effect produced in device space depends on the current transformation matrix
(CTM) in effect at the time the path is stroked. If the CTM specifies scaling by
different factors in the horizontal and vertical dimensions, the thickness of
stroked lines in device space will vary according to their orientation.
how do I convert the line width to device space using the CTM?
The line width essentially is the line size perpendicular to its direction. Thus, to calculate the width after transformation using the CTM, you choose a planar vector perpendicular to the original line whose length is the line width from the current graphics state, apply the CTM (without translation, i.e. setting e and f to 0) to that vector (embedded in the three dimensional space by setting the third coordinate to 1) and calculate the length of the resulting 2D vector (projecting on the first two coordinates).
E.g. you have a line from (0,0) to (1,4) in current user space coordinates with a width of 1. You have to find a vector perpendicular to it, e.g. (-4,1) by rotating 90° counter clockwise, and scale it to a length of 1, i.e. ( -4/sqrt(17), 1/sqrt(17) ) in that case.
If the CTM is the one from #Tikitu's answer
CTM has a horizontal scaling factor of 2 and a vertical scaling factor of 1
it would be
2 0 0
0 1 0
0 0 1
This matrix would make the line from the example above go from (0,0) to (2,4) and the "width vector" ( -4/sqrt(17), 1/sqrt(17) ) would be transformed to ( -8/sqrt(17), 1/sqrt(17) ) (the CTM already has no translation part) with a length of sqrt(65/17) which is about 1.955. I.e. the width of the resulting line (its size perpendicular to its direction) is nearly 2.
If the original line would instead have been (0,0) to (4,1) with width 1, a width vector choice would have been ( -1/sqrt(17), 4/sqrt(17) ). In that case the transformed line would go from (0,0) to (8,1) and the width vector would be transformed to ( -2/sqrt(17), 4/sqrt(17) ) with a length of sqrt(20/17) which is about 1.085. I.e. the width of the resulting line (perpendicular to its direction) is slightly more than 1.
You seem to be interested in the "corners" of the line. For this you have to take start and end of the transformed line and add or subtract half the transformed width vector. In the samples above:
(original line from (0,0) to (1,4)): ( -4/sqrt(17), 1/(2*sqrt(17)) ), ( 4/sqrt(17), -1/(2*sqrt(17)) ), ( 2-4/sqrt(17), 4+1/(2*sqrt(17)) ), ( 2+4/sqrt(17), 4-1/(2*sqrt(17)) );
(original line from (0,0) to (4,1)): ( -1/sqrt(17), 2/sqrt(17) ), ( 1/sqrt(17), -2/sqrt(17) ), ( 8-1/sqrt(17), 1+2/sqrt(17) ), ( 8+1/sqrt(17), 1-2/sqrt(17) ).
Don't forget, though, that PDF lines often are not cut off at the end but instead have some cap. And furthermore remember the special meaning of line width 0.
I don't know anything about PDF internals, but I can make a guess at what that passage might mean, based on knowing a bit about using matrices to represent linear transformations.
If you imagine your stroked line as a rectangle (long and thin, but with a definite width) and apply the CTM to the four corner points, you'll see how the orientation of the line changes its width when the CTM has different horizontal and vertical scaling factors.
If your CTM has a horizontal scaling factor of 2 and a vertical scaling factor of 1, think about lines at various angles:
a horizontal line (a short-but-wide rectangle) gets its length doubled, and it's "height" (the width of the line) stays the same;
a vertical line (a tall-and-thin rectangle) gets it's width doubled (i.e., the line gets twice as thick), and it's length stays the same;
lines at various angles get thicker by different degrees, depending on the angle, because they get stretched horizontally but not verticallye.g.
the thickness of a line at 45 degrees is measured diagonally (45 degrees the other way), so it gets somewhat thicker (some horizontal stretching), but not twice as thick (the vertical component of the diagonal didn't get bigger). (You can figure out the thickness with two applications of the Pythagorean theorem; it's about 1.58 times greater, or sqrt(5)/sqrt(2).)
If this story is correct, you can't convert line width using the CTM: it is simply different case-by-case, depending on the orientation of the line. What you can convert is the width of a particular line, with a particular orientation, via the trick of thinking of the line as a solid area and running its corners individually through the CTM. (This also means that "the same" line, with the same thickness, will look different as you vary its orientation, if your CTM has different horizontal and vertical scaling factors.)

opengl texture mapping off by 5-8 pixels

I've got a bunch of thumbnails/icons packed right up next to each other in a texture map / sprite sheet. From a pixel to pixel relationship, these are being scaled up from being 145 pixels square to 238 screen pixels square. I was expecting to get +-1 or 2 pixel accuracy on the edges of the box when accessing the texture coordinates, so I'm also drawing a 4 pixel outline overtop of the thumbnail to hide this probable artifact. But I'm seeing huge variations in accuracy. Sometimes it's off in one direction, sometimes the other.
I've checked over the math and I can't figure out what's happening.
The the thumbnail is being scaled up about 1.64 times. So a single pixel off in the source texture coordinate could result in around 2 pixels off on the screen. The 4 pixel white frame over top is being drawn at a 1-1 pixel to fragment relationship and is supposed to cover about 2 pixels on either side of the edge of the box. That part is working. Here I've turned off the border to show how far off the texture coordinates are....
I can tweak the numbers manually to make it go away. But I have to shrink the texture coordinate width/height by several source pixels and in some cases add (or subtract) 5 or 6 pixels to the starting point. I really just want the math to work out or to figure out what I'm doing wrong here. This sort of stuff drives me nuts!
A bunch of crap to know.
The shader is doing the texture coordinate offsetting in the vertex shader...
v_fragmentTexCoord0 = vec2((a_vertexTexCoord0.x * u_texScale) + u_texOffset.s, (a_vertexTexCoord0.y * u_texScale) + u_texOffset.t);
gl_Position = u_modelViewProjectionMatrix * vec4(a_vertexPosition,1.0);
This object is a box which is a triangle strip with 2 tris.
Not that it should matter, but matrix applied to the model isn't doing any scaling. The box is to screen scale. The scaling is happening only in the texture coordinates that are being supplied.
The texture coordinates of the object as seen above are 0.00 - 0.07, then in the shader have an addition of an offset amount which is different per thumbnail. .07 out of 2048 is like 143. Originally I had it at .0708 which should be closer to 145 it was worse and showed more like 148 pixels from the texture. To get it to only show 145 source pixels I have to make it .0.06835 which is 140 pixels.
I've tried doing the math in a calculator and typing in the numbers directly. I've also tried doing like =1305/2048. These are going in to GLfloats not doubles.
This texture map image is PNG and is loaded with these settings:
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
but I've also tried GL_LINEAR with no apparent difference.
I'm not having any accuracy problems on other textures (in the same texture map) where I'm not doing the texture scaling.
It doesn't get farther off as the coords get higher. In the image above the NEG MAP thumb is right next to the HEAT MAP thumb and are off in different directions but correct at the seam.
here's the offset data for those two..
filterTypes[FT_gradientMap20].thumbTexOffsetS = 0.63720703125;
filterTypes[FT_gradientMap20].thumbTexOffsetT = 0.1416015625;
filterTypes[FT_gradientMap21].thumbTexOffsetS = 0.7080078125;
filterTypes[FT_gradientMap21].thumbTexOffsetT = 0.1416015625;
==== UPDATE ====
A couple of things off the bat I realized I was doing wrong and are discussed over here: OpenGL Texture Coordinates in Pixel Space
The width of a single thumbnail is 145. But that would be 0-144, with 145 starting the next one. I was using a width of 145 so that's going to be 1 pixel too big. Using the above center of pixel type math, we should actually go from the center of 0 to the center of 144. 144.5 - 0.5 = 144.
Using his formula of (2i + 1)/(2N) I made new offset amounts for each of the starting points and used the 144/2048 as the width. That made things better but still off in some areas. And again still off in one direction sometimes and the other other times. Although consistent for each x or y position.
Using a width of 143 proves better results. But I can fix them all by just adjusting the numbers manually to work. I want to have the math to make it work out right.
... or.. maybe it has something to do with min/mag filtering - although I read up on that and what I'm doing seems right for this case.
After a lot of experiments and having to create a grid-lined guide texture so I could see exactly how far off each texture was... I finally got it!
It's pretty simple actually.
uniform mat4 u_modelViewProjectionMatrix;
uniform mediump vec2 u_texOffset;
uniform mediump float u_texScale;
attribute vec3 a_vertexPosition;
attribute mediump vec2 a_vertexTexCoord0;
The precision of the texture coordinates. By specifying mediump it just fixed itself. I suspect this also would help solve the problem I was having in this question:
Why is a texture coordinate of 1.0 getting beyond the edge of the texture?
Once I did that, I had to go back to my original 145 width (which still seems wrong but oh well). And for what it's worth I ended up then going back to all my original math on all the texture coordinates. The "center of pixel" method was showing more of the neighboring pixels than the straight /2048 did.

How to change the anchor point from the top-left corner of a transformation matrix to the bottom-left corner?

Say, I have an image on an HTML page.
I apply an affine transformation to the image using CSS3 matrix function.
It looks like:
img#myimage {
transform: matrix(a, b, c, d, tx, ty);
/* use -webkit-transform, -moz-transform etc. */
}
The origin of an HTML page is the top-left corner and the y-axis is inverted.
I'm trying to put the same image in an environment (cocos2d) where the origin is the bottom-left corner and the y-axis is upright.
To get the same result in the other environment, I need to transform the origin somehow and reflect that in the resulting CGAffineTransform.
It would be great if I can get some help with the matrix math that goes here. (I'm not so good with matrices.)
The following formula would work,
for converting the position from CSS3 to Cocos2d:
(screen Size - "y" position in CSS3 - height of object)
Explanation:
To make the origin for the Cocos environment same as for the CSS3 environment we would only have to add the screen size to the cocos2d's bodies y co-ordinate.
Eg. The screen size is (100,100) and the body is a point object if you place it at (0,0) in CSS3 it would be at the top left corner. If we add the screen size to the y co-ordinates for cocos2d the object would be placed at (0,100) which is the top-left corner for cocos2d as well
To make the co-ordinates same, since the Y axis is inverted, we have to subtract the "Y" co-ordinate given in CSS3 from the Screen Size for Cocos2d. Suppose we place the same point object in the previous example at (0,10) in CSS3 we would place it at (0, 100 - 10) in cocos2d which would be the same positions on the screen
Since our body would NOT always be a point object we have to take care of its anchor point as well. If suppose the body's height is 20 and we place it at (0,10) in CSS3 then it would be placed at the top-left position and would be coming down because the Y axis is inverted
Hence we would also have to subtract the body's total height from the screen size and "y" co-ordinate to place it at the same position which would be (0, 100 - 10 - 20) putting the body at the same place in cocos2d environment
I hope I am correct and clear :)

Quartz scaling sprite vertical range but not horizontal when go to fullscreen mode / increase window size

I have create a Quartz composition for use in MAC OS program as part of my interface.
I am relying on the fact that when you have composition sprite movement (a text bullet point in my case) is limited both in the X plane and Y plane to minimum -1 and maximum +1.
When I scale up the window / make my window full screen, I find that the horizontal plane (X axis) remains the same, with -1 being my far left point and +1 being my far right point. However the vertical plane (Y axis) changes, in full screen mode it goes from -0.7 to +0.7.
This scaling is screwing with my calculations. Is there anyway to get the application to keep the scale as -1 to +1 for both horizontal and vertical planes? Or is there a way of determining the upper and lower limits?
Appreciate any help/pointers
Quartz Composer viewer Y limits are usually -0.75 -> 0.75 but it's only a matter of aspect ratio. X limits are allways -1 -> 1, Y ones are dependents on them.
You might want to assign dynamically customs width and heigth variables, capturing the context bounds size. For example :
double myWidth = context.bounds.size.width;
double myHeight = context.bounds.size.height;
Where "context" is your viewer context object.
If you're working directly with the QC viewer : you should use the Rendering Destination Dimensions patch that will give you the width and the height. Divide Height by 2, then multiply the result by -1 to have the other side.

OpenGL texture mapping with different coordinates systems

I already asked a question about texture mapping and these two are related (this question).
I'm working with Quartz Composer which appears to be kind specific with textures...
I have a complex polygon that I triangulate in a specific coordinate system (-1 -> 1 on x | -0.75 -> 0.75 on y). I obtain an array of triangles vertices in this coordinate system (triangles 1 to 6 on the left pic).
Then I render each polygon separately (it's necessary for my program), by applying a scale function on its vertices from this coordinate system to OpenGL one (0. -> 1.). Here, even if for 0->1 range it's kind of stupid :
return (((1. - 0.) * (**myVertexXorY** - minTriangleBound)) / (maxTriangleBound - minTriangleBound)) + 0.;
But I want one image to be textured on these triangles (like on the picture above). So I begin by getting the whole polygon bounds (1 on the right pic), then the triangle bounds (2 on the right pic). I scale 1 to the picture coordinates (3 on the right pic) in pixels, then I get the triangle bounds (2) in pixels.
It gives me the bounds to lock my texture in OpenGL with Quartz :
NSRect myBounds = NSMakeRect(originXinPixels, originYinPixels, widthForTheTriangle, heightForTheTriangle);
And I lock my texture
[myImage lockTextureRepresentationWithColorSpace:space forBounds:myBounds];
Then, with OpenGL :
for (int32 i = 0; i < vertexCount; ++i)
{
verts[i] = myTriangle.vertices[i];
texcoord[0] = [self myScaleFunctionFor:XinQuartzCoordinateSystem From:0 To:1]
texcoord[1] = [self myScaleFunctionFor:YinQuartzCoordinateSystem From:0 To:1]
glTexCoord2fv(texcoord);
}
And I obtain what you can see : sometimes parts of the image are fitting, sometimes no (well, in fact with this particular polygon, it doesn't fit at all...).
I'm not really sure if I did understand your question, but:
What hinders you from directly supplying texture coordinates that do match the topology of your source picture? This was far easier than trying to find some per triangle linear mapping that moves the picture in the right way.