Jump to content

  • Log In with Google      Sign In   
  • Create Account

Erik Rufelt

Member Since 17 Apr 2002
Offline Last Active Today, 05:54 PM

#5197966 Text rendering and low FPS in game.

Posted by Erik Rufelt on 13 December 2014 - 06:40 AM

This largely depends on the strings and how they are formatted internally. Do the strings change each frame or are they static?


I wrote the FW1 library, and it uses DirectWrite to construct the text layouts which is quite slow if done each frame, as the whole internal layout is reconstructed each time. The solution is to save the geometry of strings that are static, and not do the whole text-layout again until the characters in a string changes.

If you use that library there are "Samples" projects to download including one called ManyStrings: http://fw1.codeplex.com/releases/view/75558


For the sprite-font class you need to check its internals, it should have some way of caching the results or similar. If the strings are truly static the best way is to save the vertex-buffer and just draw the same triangles again and only update the buffer when the characters change.


If you draw constantly changing strings, like some kind of matrix-effect where the characters flash really quickly, then you probably don't want any fancy text-layouts like DirectWrite uses, which is optimized to display text prettily and not fast, and rather write your own method.

The easiest is to treat each character as a quad with some texture coordinates and a fixed distance to the next character, which can be implemented with a table and a very simple and fast loop.

#5195645 NULL vs nullptr

Posted by Erik Rufelt on 01 December 2014 - 01:29 AM



As the value of nullptr is just 0, I'd say it's irrelevant for C functions as they can't be overloaded. I usually use NULL when I use an API with a specification that says NULL, and nullptr otherwise, just for consistency.

#5195223 Super Cool Effects

Posted by Erik Rufelt on 28 November 2014 - 11:02 AM

glBlendFunc(GL_ONE, GL_ONE) usually does it :)

#5194902 OpenGL 5 - Release?

Posted by Erik Rufelt on 26 November 2014 - 10:42 PM

From http://en.wikipedia.org/wiki/OpenGL#OpenGL_NG


This is a codename given by journalists to a grounds-up redesign effort (semi-officially called "The Next Generation OpenGL Initiative"), to unify OpenGL and OpenGL ES into one common API that will not be backwards compatible with existing OpenGL versions.


"to unify OpenGL and OpenGL ES into one common API" can be important to some developers.

At the same time I guess it will make a lot of features optional which could complicate things, though hopefully there will be some sort of IsDesktop() or IsES() so we don't have to handle too many different cases.

#5193918 Correct order to multiply matrices in 2D space

Posted by Erik Rufelt on 20 November 2014 - 11:53 PM

The order in which translate and scale is done is swapped when you swap the multiplication order.


So the first one first inverts Y, then moves the square, whereas the second first moves the square, and then flips the already moved square around Y.


I guess in your case, Y = 0 is at the edge of the screen, and if you first flip the square and then move it into the screen it will be visible.

If you instead move the square into the screen, and then afterwards flip it around Y, then it will be flipped with its translation so the final position will be in the opposite direction outside the screen.

#5185824 OpenSSL tutorials?

Posted by Erik Rufelt on 08 October 2014 - 01:38 PM

There is built-in support for it in Windows APIs, for handshakes and encrypt/decrypt. Found this for example, that wraps send/recv on a socket to properly encode the data: http://www.codeproject.com/Articles/24379/SSL-Convert-your-Plain-Sockets-to-SSL-Sockets-in-a

#5184463 float error that i cant fix, (d3d9 related)

Posted by Erik Rufelt on 01 October 2014 - 09:00 PM

The name "INFINITY" is probably already defined as something else (like in Windows.h or D3D9.h). Just use FLT_MAX instead of renaming it.

Also, "infinity" is a bad name for it, as they are not the same thing and you can do for example FLT_MAX / 2 and get a new number that is no longer FLT_MAX.

#5182110 frac(x) results in strange artifacts when x is close to zero

Posted by Erik Rufelt on 22 September 2014 - 09:03 AM

You'll have a discontinuity at the edge, where the texture coord hops from 0.999 to 0.001.. so it could be that when mipmaps are enabled the graphics card thinks that you're trying to draw the entire texture with minification so it fits in between those two pixels at the edge, which will cause it to always choose the smallest mip-level.

Such usage is probably better without mip-maps... or just skip the frac(), as it shouldn't be needed, you can just rely on repeating wrap mode for textures.

#5181963 Fear of replacement

Posted by Erik Rufelt on 21 September 2014 - 04:34 PM

Should I tomorrow correct that senior guy about the term ray casting that I was true in-front of everyone and clear up my image :/ ?


No, why in the world would you do something like that?

That actually might get you fired, or at the very least make people think badly of you, and would probably even make some idiot cause more problems just to see what you will do.


I mean think about how that will sound: "Last week you were an idiot to me for making me look bad, look here I was right!!!  Everyone look I was right!!". What would you think if someone else did that?

Being wrong isn't even that bad... if you can choose between people thinking you were wrong even though you were right, and people knowing you are right but thinking you care that much about it... just let them think you were wrong, it's better for you.


Smile and never say a thing and keep doing good work, and find your next job ASAP and try your luck elsewhere. And when you quit, still smile and thank everyone for a good time.


Also, you don't really seem to like it where you are... maybe try to go where you're happy and like people.

#5181879 [Solved] Segfault in DrawElements; I cannot find the problem

Posted by Erik Rufelt on 21 September 2014 - 07:12 AM

In general you have to set a minimum GL version, say for example you select GL 3.3 as your minimum platform, and then you can check the specification for what is supported for that version.

Then you can use glGet to get some implementation-defined limits if you want to use something that isn't guaranteed to be supported, like glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &number) to find out how many vertex attribs you can send to your shader. However, the reference page says that the minimum required is 16, so you only have to bother when using more than that.





The 4.5 specification has a table for vertex attrib support it appears, if you click the glVertexAttrib* in the menu and scroll to the bottom of the page.

#5181872 [Solved] Segfault in DrawElements; I cannot find the problem

Posted by Erik Rufelt on 21 September 2014 - 06:40 AM

Are you sure the GL_DOUBLE vertex format is supported by your GL driver?


#5181731 X11 Keep window on top

Posted by Erik Rufelt on 20 September 2014 - 11:26 AM

This perhaps?



Not too familiar with X11, but can't you make the tool-window a child-window or something, or is that not acceptable?

#5181548 Why does divison by 0 always result in negative NaN?

Posted by Erik Rufelt on 19 September 2014 - 09:02 AM

This page explains a bit on what optimizations are allowed under different floating point behavior settings in VC++:



For example:


Expression optimizations that are invalid for special values (NaN, +infinity, -infinity, +0, -0) are not allowed. The optimizations x-x => 0, x*0 => 0, x-0 => x, x+0 => x, and 0-x => -x are invalid for various reasons. (See IEEE 754 and the C99 standard.)




I suspect we're simplifying this whole problem by saying "optimizes stuff relying on undefined behavior out"... even though I don't usually proclaim "formats C:", I think when division by zero can do anything, a later statement being optimized out isn't the major issue.

It's easy to add a _controlfp() in a program that makes it crash on division by zero, if that's the behavior we want. Though it can be very useful for a Debug build, for me it's usually isn't at all acceptable in a final product, and on the contrary I want it to absolutely not crash, since I specifically do not want to have to marshall my values. What we're considering is basically this (all __assumes auto-added by compiler):

float r = n / d;
__assume(d nonzero);

What are we really assuming here?

That IF the implementation happens to accept division, and the program continues, we assume that d wasn't zero? Or are we assuming that a division by zero will never occur at all?

If it's the latter, would this also be OK?

__assume(d nonzero);
float r = n / d;

If so, consider this:

assert(!isnan(n) && !isnan(d));
__assume(n, d not nan);

__assume(d not zero);
float r = n / d;
__assume(r not nan); // can't possibly happen

if(isnan(r)) {
  // optimized out?

When floats are used as acceptable approximations, and functions are expected to hit singularities on numerical instability, a floating point mode that gracefully handles Inf and NaN is very desirable, and incredibly useful for performance-sensitive approximating algorithms. As such I think that even if a standard doesn't explicitly define it, every major implementation will at the least implement it as an option for targets that is expected to support it.


Also, if we use something like fast-math or just generally accept floats as approximations that don't always round exactly the same, then it's not like with integers where we can guarantee that a number won't ever be zero, and value-marshalling would have to be added at unreasonably many points in the code if we were to guarantee that no division by zero ever occured. Basically we would have to revert to something like this:

float result;
int err = tryFloatOp(f0, f1, &result);
if(!succeeded(err)) {
 return default();

I definitely think there are times where division by zero is expected to and should be undefined for floats, for example in mathematical computations that aren't supposed to deteriorate, and an exception is the correct result on division by zero. But I don't think that it's acceptable for an implementation to have it both ways, and generate code that expects division by zero to work perfectly fine, and still remove pieces of code that won't be hit unless that division by zero actually takes place.



EDIT: Another example where all if-statements could be removed if we assume the user will never input a zero divisor:

#include <iostream>

int main() {
	int i0;
	std::cin >> i0;
	float f0 = static_cast<float>(i0);

	int i1;
	std::cin >> i1;
	float f1 = static_cast<float>(i1);

	float r = f0 / f1;

	std::cout << "Answer is " << r << std::endl;

		std::cout << "Answer is NaN!" << std::endl;
		std::cout << "Answer is Infinity!" << std::endl;
	if(f1 == 0.0f)
		std::cout << "The divisor was zero" << std::endl;

	return 0;

#5181328 Why using std::string when you can create it yourself...

Posted by Erik Rufelt on 18 September 2014 - 12:41 PM

My favorite:

data[strlen(data)] = '\0';

#5181239 BSP trees with modern OpenGL

Posted by Erik Rufelt on 18 September 2014 - 05:29 AM

Ok, so basically: Just take your translucent (sub)meshes, order them back to front and render then in that order. But exactly how do I correctly order them back to front in a reliable manner if BSP trees can't be used?



Firstly, for it to work entirely correct your submeshes must be convex and non-intersecting (or they would need to have their polygons sorted too for perfect close-ups), though if they're nearly so you might get away with it anyway. Then after that you could sort based on Z or distance to the camera, from the closest point on the objects bounding-sphere/box.