Jump to content

  • Log In with Google      Sign In   
  • Create Account

Calling all IT Pros from Canada and Australia.. we need your help! Support our site by taking a quick sponsored surveyand win a chance at a $50 Amazon gift card. Click here to get started!


Brother Bob

Member Since 26 Nov 2001
Offline Last Active Today, 01:43 PM

#5249762 acos ( ) in Java has gone bezierk

Posted by Brother Bob on Yesterday, 02:20 PM

It's 1.325 radians, which is the same as 75.930 degrees.




#5242690 Technical audio questions?

Posted by Brother Bob on 25 July 2015 - 04:41 PM

For technical questions, there are a few suitable places for different kinds of audio related questions. You have Maths and Physics for mathematical and theoretical questions, APIs and Tools if you have problems with specific audio APIs, and then there's always the last resort for anything related to programming: General Programming. Pick a place that seems suitable; we'll move it if it's entirely out of place.




#5242402 Vector cast

Posted by Brother Bob on 24 July 2015 - 08:26 AM

Assuming you're using C++, have the Add function take a const reference instead so you can pass temporary objects to it and your two last examples will be fine. Temporary objects cannot bind to non-const references.




#5241077 Texturing occasionally off by a pixel

Posted by Brother Bob on 17 July 2015 - 10:56 AM

 

...but I just want to open the possibility that if you have to correct this at several places around your code base, then maybe it wasn't designed with integer coordinates in mind to begin with? smile.png

 
Ironically, it was/is, but I switched to floats (~8 months ago) because that was what OpenGL expects, and so motion can be "smoother" for moving objects.
pos += (velocity * deltaTime);
If 'pos' is integer, then I was thinking it might give more jittery movement. In situations like movement, wouldn't it be better to accumulate the decimal portion over time?

 

Keeping floating point positions, velocities, accelerations, time and such is fine. Fractional motion can be achieved with integers as well, look for example at how Bresenham's line algorithm works: it can move fractional distances along the Y-axis as you sweep along the X-axis where the X distance is greater than the Y-distance all with integer pixel locations.

 

 

 

Joke aside; only the output from the vertex shader has to produce integer coordinates. Any intermediate calculation can, technically, be done in full decimal arithmetics, but just make sure you round the result in one place: the output from the vertex shader.


That's a thought - so you're saying I might be able to just get away with:
gl_Position = (ModelViewProjectionMatrix * vec4(round(vPosition), 0.0f, 1.0f));

 

If anything it has to be round(ModelViewProjectionMatrix * vec4(...)); Remember, the final coordinates has to be integers. This is probably the simplest solution, along with full floating point values for intermediate calculations. You are still at the mercy of rounding errors, but at this point the errors are on the order of floating point epsilon rather than half a pixel.




#5241020 Texturing occasionally off by a pixel

Posted by Brother Bob on 17 July 2015 - 03:53 AM

Thanks guys, that helps a bundle.
 
I've temporarily enabled Linear filtering, for testing - previously I had it on Nearest, because Linear isn't what I want for 2D artwork (it's also Nearest for mipmaps, because I intend to store additional unrelated spritesheets in the mipmap levels).

If done correctly, it shouldn't matter which filter mode you use. From a debugging perspective, using full linear interpolation both along the texel axes and the mipmap axis is arguably better, since everything should be perfectly aligned anyway and any misalignment will be visible as a result. Of course, use nearest filtering for production when you're certain everything is correct.

 

So I'm "fixing" the problem currently by using std::round() on the values before I send them to the videocard - both on the camera position and on the polygon positions.
 
Visual it works, but software design-wise is this the right way to go about fixing it? With the camera it feels right, but with the polygons - either I'm doing it low-level and rounding everything right before it's uploaded to a VBO, which feels wasteful and hackish, or I'm doing it higher level and doing it when positioning polygons - which means there'll eventually be twenty or thirty places in my code where I need to make sure to round values, and if I miss one, it can visually give bad results - though this does seem the more correct way.

Correct design or not, absolutely no fractional coordinates can come out from the vertex shader in the end. It is of course hard to comment on your, for me unknown, design, but I just want to open the possibility that if you have to correct this at several places around your code base, then maybe it wasn't designed with integer coordinates in mind to begin with? smile.png

 

Joke aside; only the output from the vertex shader has to produce integer coordinates. Any intermediate calculation can, technically, be done in full decimal arithmetics, but just make sure you round the result in one place: the output from the vertex shader. This may even give you better result as you're not rounding decimal values all the time. If you do rotations and other transformations and keep rounding intermediate results, you will keep adding rounding errors up to 0.5 pixels at every stage. That could add up to several pixels worth of error, just not tiny normal floating point rounding errors.

 

Keeping coordinates internally in decimal precision and just round for the purpose of rendering is totally fine. Just keep in mind that you are then still subject to rounding errors. For example, if you need to keep two independent sprites just next to each other on a pixel-basis, the two objects may be transformed slightly different and causing them to sometimes be rendered with a pixel between them or with a pixel overlapping. That may not be an issue in a situation like in your images above.




#5240632 Texturing occasionally off by a pixel

Posted by Brother Bob on 15 July 2015 - 06:10 PM

[Edit 2:] I've confirmed that the camera position's fractional value is basically setting the fractional value of the object's position, which sets the default fractional value of the corner quads being rendered. So basically, any object that I've placed but haven't yet moved the camera on, will be something like QuadPos = xx.125, CameraPos = yy.125.

 

Speculation: So when subtracting the camera pos from the quad's pos (which I'm assuming the MVP matrix basically does), will result in the quad having an xx.000 fractional value after the vertex shader, which might get rounded the wrong when rasterizing in the fragment shader?

You edited this as posted by reply, and I just wanted to address this particular bit since it could be the source of misunderstanding.

 

The rasterinzation rules in OpenGL essentially state that a pixel is rasterized if its center is located within the boundary of the triangle. A pixel's coordinate in "pixel space" range from (x,y) at its lower-left corner (or upper-right, or upper-left, or whatever depending on the orientation of the projection matrix) to (x+1, y+1) at its upper-right corner, and the pixel's center is located at (x+.5, y+.5).

 

So if you have a quad corner located at (x+.5, y+.5), you are at the mercy of rounding errors whether that pixel is located just inside or just outside the quad. An integer coordinate (x,y) on the other hand has a good margin; it has to be off by 0.5 units before reaching a pixel center where the rasterization happens. The quad at a corner (x,y) covers the corner pixel to 100%, and the neighbouring three pixels to 0%, so there's absolutely no ambiguity which pixels are rendered.




#5240630 Texturing occasionally off by a pixel

Posted by Brother Bob on 15 July 2015 - 06:00 PM

If you want pixel perfect rendering, you're going to have to precisely control the coordinates to ensure that they are always integer coordinates after any applied transformation. That means you cannot have fractional translations in your ModelViewProjectionMatrix matrix either. After rotating the objects, round the resulting values to snap them to precise pixel locations. All points you show have fractional coordinates and that won't play well with pixel perfect rendering.

 

I don't have a direct answer to the problem itself, but I recommend that you start from scratch to get familiar with how pixel perfect rendering works in OpenGL and work from there to isolate your current problem. For visual debugging purpose, turn on linear texture filtering to ensure that texels are perfectly aligned with the pixels (the texture will look sharp when aligned, and blurry when not) and enable polygon smoothing (glEnable(GL_POLYGON_SMOOTH), although not sure if that's still in the core profile contexts beyond OpenGL 3.0)  and alpha blending to ensure that your quads are rendered on exact pixel boundaries as well. Take a screenshot and inspect the result close-up on a pixel basis to ensure that the texture is rendered sharp, there's no leakege from pixel smoothing around the border of your quad, and that there are exactly the correct number of pixels being rendered.

 

In the end, the rasterization rules are well defined and quite easy to set up. But fractional coordinates are your enemy here, especially a 0.5 pixel offset.




#5240606 Texturing occasionally off by a pixel

Posted by Brother Bob on 15 July 2015 - 03:54 PM

For filled primitives, such as triangles and other surfaces you put your texture on, you don't offset your coordinates at all. The offset should only be applied to line and point primitives. Assuming, of course, that you apply the usual projection matrix such as glOrtho(0, width, 0, height) or some similar variant thereof.




#5231506 Extremely weird, illogical bug. Part of false if clause executed.

Posted by Brother Bob on 28 May 2015 - 11:01 AM


Description is a WCHAR[128]. You then take the address of that. Then you cast that address, which is a WCHAR **, to a WCHAR *.
 

The type of &adapterDesc.Description is WCHAR (*)[128], not WCHAR **. The types on either side of the assignment are ultimately different and incompatible, but the pointer is likely going to end up pointing to the first element of the Description array anyway in practice, setting aside all the theoretical problems.




#5230885 OpenGL vs DirectX

Posted by Brother Bob on 25 May 2015 - 01:42 PM

What fastcall said.




#5228949 How to add vertices in a VBO

Posted by Brother Bob on 14 May 2015 - 07:49 AM

You can change the content of a buffer in various ways, for example by calling glBufferSubData or by mapping the content to memory with glMapBuffer. If your buffer content can change in size, then start with a large buffer and draw only the necessary part of it so you can expand it later when needed without having to relocate the entire buffer.




#5224922 C++ Ternary operator ?: surprising conversion rules.

Posted by Brother Bob on 22 April 2015 - 03:42 PM

Is the condition supposed to be false?

 

I assume it's supposed to be false, yes. The interesting part of that code happens when the false-expression is evaluated.




#5223336 Template or Macro

Posted by Brother Bob on 14 April 2015 - 11:47 PM

There are a few templates in the standard library for safe delete already: here, hereand here, for example. So the standard apparently thought it was better to use templates in this case at least.




#5222784 How does boost::shared_ptr/make_shared equality work?

Posted by Brother Bob on 12 April 2015 - 12:48 PM

For the purpose of explaining it in simple terms: yes, your heap allocated object can be managed by the shared pointer, but the stack allocated object cannot.




#5222772 How does boost::shared_ptr/make_shared equality work?

Posted by Brother Bob on 12 April 2015 - 11:28 AM

Partly correct, given the actual wording you use. The different smart pointers are about managing ownership of the instance in various ways, but automatic objects are already owned and managed by the surrounding scope. The automatic ownership is not compatible with the shared ownership provided by the shared pointer.

 

You can, however, pass ownership to an existing object, but it has to be something that you can pass the ownership of. Dynamically allocated objects can have their ownership transferred, but automatic objects like you asked about cannot.

// allocat an object
Object *o = new Object;

...

// pass the object to the shared pointer and give it full ownership
shared_ptr<Object> s(o);





PARTNERS