Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 14 Feb 2007
Offline Last Active Today, 07:35 AM

#5309583 How Important is Concept Art?

Posted by on 05 September 2016 - 07:48 PM

Echoing the above statements about use in teams, it's also a time saving exercise. While the 3D artists are still busy finishing game A, the concept art team can begin exploring game B, and actually polish the design of every character, vehicle, important object, location, lighting mood, background scene... All before actual production on game B has actually started. This is very important for scheduling and budgeting, while still having control over what it is you're going to build.

#5309580 hierarchical task network planner using Multithreading

Posted by on 05 September 2016 - 07:41 PM

- Planners can find the list of tasks faster using multithreading
- When changing the world state, it needs to lock the variable so that race condition would not happen.

Modern engines don't really do threading that way any more. You wouldn't have an "AI thread" that runs concurrently with a "game thread". Instead, you have one thread per hardware core and you break up all of your code into a directed acyclic graph of dependent tasks, which are executed across all threads automatically. There's no locking, as jobs are only scheduled to execute when their dependencies have already completed... But yes, you will compute plans faster, which is the point of using every core to execute the game code :D
Once you start writing code in this 'job DAG' style, then all of your code is magically multithreaded in the same way -- the actual problem domain (AI planning, physics, graphics, game rules) doesn't matter, it's all just jobs in a job-graph.

#5309509 Hostility in the field

Posted by on 05 September 2016 - 06:31 AM

Hodgman, I find it telling that between the two possibilities of someone having a friend (after all this, calling him a mere acquaintance seems rude - God knows he could use an ally if this is the battlefield he has to fight on) willing to go to bat for him, and the same person inventing a complete being out of whole cloth, you pick the latter.
Frankly, I don't care what you believe.

I only brought it up as a possibility seeing as you're posting under a duplicate account, and your previous account only started a single topic here, which went exactly the same as this one... and where you described yourself in the same way that you're describing your friend now.

You've got to admit that these actions of yours give me cause to suspect that your abused friend is yourself.

So, technically, the field is not actively hostile - it's just so cold, so callous, so indifferent to the demoralisation (thank you, Kylotan) that it creates, that a person who has been abused his entire childhood could be forgiven if he confused such lack of compassion with hostility.
May God have mercy on you all.

You're talking to all of us as if we're all the people who have abused you. I'm not them. I've tried to help you, but my help is not what you need. Good luck.

#5309489 Outsourcing Team - 3D Simulation

Posted by on 05 September 2016 - 02:25 AM

Although we're Aussie based so somewhere in line with our time zone is preferable

Get in touch with the GDAA - they're the local industry representatives, who's job is to know/support everyone. I'm sure Tony would be happy to forward on details about your situation throughout the local industry for you in order to help you find someone suitable. There's quite a few small local studios that are available for work-for-hire. Disclaimer: I'm one of the small studios that's picked up work that's been shopped around this way :D


While working at some of the larger studios here, I've experienced them taking on mining/defense/training simulation work alongside their main games business, and at the small end of town as an independent start-up, I see the same thing!

#5309476 Multi thread rendering engine

Posted by on 05 September 2016 - 12:52 AM

There's no difference between threading graphics or any other engine system. An extremely common approach is a "job system" as described here: https://blog.molecular-matters.com/2015/08/24/job-system-2-0-lock-free-work-stealing-part-1-basics/

#5309383 Game engine advice?

Posted by on 04 September 2016 - 07:52 AM

Why not Source Engine if you like their tools? There's also any of the old Quake engines if you don't care about latest tech - even GoldSrc :)

UE4 and Unity are the most common suggestions.

You could check this out to get a more hammer-like environment in Unity: http://www.gamedev.net/topic/681626-released-realtime-csg-boolean-based-level-editor-for-unity/

#5309278 Hostility in the field

Posted by on 03 September 2016 - 01:35 AM

Hodgman: So you're saying that somewhere out there there's an office filled with companies all in the same field (theoretically) competing against each other? I can't imagine what that would be like - I assume part of the lease agreement includes no espionage or poaching; but still, the dynamics there must be unprecedented. Someone could write a thesis on the interplay there and ace it.

Read this; for the most part, game developers are not competing with each other: https://medium.com/steam-spy/your-target-audience-doesn-t-exist-999b78aa77ae#.wpqk1taap

Also, knowledge sharing within gamedev is amazingly common compared to other fields. In a previous (non-games) software job, I had a job performance indicator of whether I'd drafted one patent per month or not. It's impossible to invent one genuine breakthrough every month, so obviously this was for the purpose of hampering the competition with a large library of bullshit patents. On the other hand, every year hundreds of gamedevs appear at conferences to freely share the details of their latest work and advancements in the state of the art, patent free and usually without speaking fees... The post war idea that 'we all do better when we all do better' seems to still be alive and well rather than the post 70's alternative of 'greed is good' :D
So yeah, if people here are working on contractually super secret stuff, they'll close their (sub-)office doors, but for the most part things are pretty open, and there's a LOT of knowledge/idea/capability sharing when people mix in the common areas.
Personally, I'd find it really painful to go back to a corporate software job after working here :wink:

#5309262 Screenspace Normals - Creation, Normal Maps, and Unpacking

Posted by on 02 September 2016 - 09:46 PM

Normal maps need to be rotated from tangent space to world space anyway. This just rotates from tangent space to view space instead (same cost).

After unpacking, you only have to rotate them into world space (using the view_to_world matrix) if all your lighting data is in world space. If you put all your data in view space, this isn't an issue.

You can also just store two component normals in world space if you want to.

You actually can't just use Pythagoras to decode n.xy into n.xyz because that gives two two answers: +z and -z. You might think that this is fine because view-space normals will always point towards the camera, but *due to perspective*, this is false. It's very easy for a surface to be visible yet facing away from the camera (just look down a corridor where the floor slopes downwards)!
So, this simple packing scheme of "just drop z" actually must be "replace z with one bit" so you know which of the two decoding to use.

This page has a good listing of a variety of two component encodings:

My current favourite is octahedral:

#5309236 Faster Sin and Cos

Posted by on 02 September 2016 - 05:31 PM

But double precision runs faster than single precision version, anyway

With what compiler settings?
X86 compilers tend to produce retarded float code unless you use the fast math option to opt out of IEEE 32but strictness.

#5309156 Make this small algorithm branchless ?

Posted by on 02 September 2016 - 06:56 AM

Is there a specific reason that you're using double instead of float?


#define is evil for that usage; use an inline function - that's what they're for.
Your sign function is crazy inefficient (and in integer math!). How does that not produce compiler warnings? It translates to this:

inline int sign( double x )
	int a = (x > 0.0) ? 1 : 0;
	int b = (x < 0.0) ? 1 : 0;
	return a - b; // integer result!

And then you add it to a double, so there's an implicit int->double conversion on top. There's a lot of trust there that the compiler will figure out what you mean and fix the code...


Also, unless you need the three-result version (-1,0,1), use a two-result version, and stay in float land instead of converting to int and back:

inline float sign_bit( float x )
	return x >= 0.0f ? 1.0f : 0.0f;

The loop is bad:

for (int i = 0; i < ceil(fabs(X)); i++){
//note: X does not change within the loop.
//Don't make the compiler try to guess whether the loop body modifies the loop condition or not. 
//Make it explicit, make the compiler's job easy:
for (int i = 0, end = (int)ceilf(fabsf(x)); i != end; ++i){

Likewise, these computations are used in the loop body, but are constant, move them before the for statement:

float absx = fabsf(x);
float signx = sign_bit(x);

The loop then reduces to:

float absx = fabsf(x), signx = sign_bit(x);
for (float i = 0, end = ceilf(fabsf(x)); i < end; ++i) {
  float f = (absx-i < 1.0f) ? x-i : 1.0f; // you had an implicit int->float cast of 'i' here, may as well make the loop counter a float to avoid it
  position += f*signx;

What is this algorithm anyway? I assume there's more to it, otherwise you'd just do something like: position += x; :lol:

#5309100 What is the best PBR Real Time Fresnel function

Posted by on 01 September 2016 - 08:53 PM

For some reason I kept thinking of gloss as specular power

 Gloss / Roughness is equivalent to specular power :D



Matias was advocating both Diffuse and Specular in the metalness workflow. Is there any place for this or is it just a waste of gbuffer space? It seems like it's purely convention.

It's almost universal at the moment to use an RGB F0 parameter to control the colour of the specular highlights, and to have no other multiplier. In the metalness workflow, that's your "base colour" map / the hardcoded 0.04, and in the "specular workflow" it's your specular map.


If you follow Matias' link, and then the link to that research paper, they use a model that has a monochromatic F0 (even for metals, which is wrong!) but then also have an RGB multiplier that gets applied to the entire specular result. This extra multiplier is extremely uncommon in "PBR" game renderers at the moment -- except maybe as a "cavity" or "specular occlusion" multiplier... but as the research shows, they're managing to better match real-world material measurements by having this extra parameter.

So, should be have an extra RGB specular multiplier on top of everything else: Yes.

Are PBR games currently using an extra RGB specular multiplier in order to better match the real world: Not really, no. :(


Also note that these researchers are not using artists to create material values -- they're using an error-minimization algorithm to try and automatically choose their material values in order to match scientific measurements of real materials.

If you give their material model to an artist, they'll likely fuck it up with impossible colour values :lol:

#5309097 What is the best PBR Real Time Fresnel function

Posted by on 01 September 2016 - 08:26 PM

Hey Hodgman, I'm well aware of the two seperate workflows. My question was about how many workflows have Base Color, Specular Color, Metalness, and  Roughness. (ie: Unreal). In other papers, I see only Base, Metal, and Roughness, no specular. I see the Base is combined with the specular map, so it acts as a specular for metals and as a diffuse for nonmetals. The issue is, for nonmetals, where would the F0 then come from, if the Base Color goes to Diffuse.
EDIT: Oh, by the way, is there a free source for PBR models? Everything I find uses Gloss+Specular. Thanks!

Both spec/gloss and metal/rough can be PBR workflows (or not).
In the "specular workflow", you have:
* RGB Diffuse Colour
* RGB Specular Colour
* Glossiness (pretty much: roughness)
In the "metalness workflow", you have:
* RGB Colour
* Metalness
* Roughness (pretty much: glossiness)
You can think of this last one as being a compression algorithm for the first one.
Before doing any shading, you "decompress" your metalness data back into specular data:
diffuse = lerp( base, 0.0, metalness );
specular = lerp( 0.04, base, metalness );

i.e. for non-metals, the F0 is hard-coded to 0.04 when using the metalness workflow, and the diffuse and specular RGB maps are both generated by decoding the base-colour and metalness maps. Likewise, the diffuse colour of metals is hard-coded to 0.0.


Just to reiterate: metalness is not a property of the BRDF at all. It's a property of this texture packing scheme.

Also, do polarizing cameras only capture the diffuse of nonmetals? How would you capture textures for metals, if that's the case? As far as I know (I create my textures by hand, not camera), polarizing cameras remove specular hilights, and if a metal is all diffuse, would it actually capture? Would this be an issue at all?

Polarizing filters don't remove specular - they can be used in certain situations to remove some of the specular highlights...
* set yourself up a perfectly black room with perfectly black walls
* put an object on the floor to photograph
* put a single spot-light in there with a polarizing filter over it that only lets through vertically polarized light 
* put a camera in there with a polarizing filter over it that only lets through vertically polarized light
* take a photo
** diffuse reflections will "unpolarize" the light, turning vertically polarized light into any other kind of polarization with random chance, so your camera will capture approximately half of the diffuse reflections.
** specular reflections will not change the polarization of the light, so you will get (hopefully) all of the specular reflection.
* now rotate the filter on your camera 90º so that it only lets through horizontally polarized light
* take a photo
** you will still capture half the diffuse lighting, as it's randomly polarized
** hopefully you will capture almost none of the specular reflection
* subtract photo #2 from photo #1 and you'll have a picture of just the specular lighting ((~50% diffuse + ~100% specular) - (~50% diffuse + ~0% specular) = ~0% diffuse + ~100% specular).
In practice your room won't be perfectly black, your filters won't be perfect, your alignment won't be perfect, and the idea of "diffuse" and "specular" reflections won't perfectly match the real world, so your photos won't give you this perfect separation either.


I hadn't, though, known about interpolation issues. is there a good way to overcome it?

It's usually not even noticeable. If you're making a lot of assets with texture transitions from dark metal to light plastic, then maybe the metalness workflow isn't the best fit -- use RGB diffuse + RGB specular maps instead of RGB base + metalness maps.

#5309092 What is the best PBR Real Time Fresnel function

Posted by on 01 September 2016 - 07:42 PM

Schlick's fresnel approximation is based off IOR

The version we use in graphics is based on F0.

And I know this is sort of unrelated, so I'm not going to officially ask for it, but are there any real reasons NOT to combine specular color and base color, as Unreal has done? I can't think of a single real reason, even for more stylized stuff.

 There's two different (popular) content creation workflows - often called "spec/gloss" and "metal/rough".
The "metalness" workflow is much simpler, as you just have base colour (RGB), metalness (grey) and roughness (grey), but unfortunately this compact representation does not interpolate perfectly:

and I discovered that they initially wanted to use a F0 of 0.4 for non-metals. What would be the F0 for metals in this case

They use 0.04, which is an IOR of 1.5, which is about right for glass. Water is IOR=1.33 / F0~=0.02, and Sapphire is IOR=1.76 / F0 ~=0.08... So F0 of 0.04 is within the ballpark for most non-metals.
For metals, the F0 is much, much brighter (using the "base colour" in the metalness workflow).
e.g. Silver is IOR=0.18, which using the above formula gives F0~=0.48. However, the above formula for converting between F0/IOR is an approximation of the real physics, which only works well for non-metals... In reality, Silver has an F0 value of more like 0.95 IIRC! When doing the conversion for metals, you also need to know it's IOR as a complex number, where the real part is used as normal, and the complex part becomes an extinction coefficient.
I think the formula for metals is: F0=((n-1)^2 + k^2)/((n+1)^2+k^2), where n is the real part of the IOR and k is the imaginary part, so if we said that Silver had an IOR of 0.18+8.4i, then it's F0 would be 0.99
Note though that the IOR value for a material depends on the wavelength of light that you're using to measure it. For non-metals, this wavelength-dependent graph tends to be pretty flat, so a greyscale IOR/F0 value is fine... but for metals, the graph tends to be sloped through the visibile spectrum, so the IOR/F0 value for Red, Green, and Blue wavelengths will be different, which is why you need an RGB F0 map.

#5308935 Passing groupshared memory to functions

Posted by on 31 August 2016 - 07:14 PM

The equivalent to pass-by-pointer for mutable parameters is the out or inout keywords:

void WriteTo( out float4 result, float4 data )
    result = data;
groupshared float4 g_data; 
void test()
  WriteTo( g_data, float4(1,2,3,4) )
void WriteTo( out float4 result[8][8], float4 data, uint2 thread )
    result[thread.y][thread.x] = data;
groupshared float4 g_tile8x8[8][8]; 
void test(uint2 thread : SV_GroupThreadID)
  WriteTo( g_tile8x8, float4(1,2,3,4), thread )

#5308893 Custom Shader Builder

Posted by on 31 August 2016 - 02:44 PM

In the sdk, there's a command line tool called FXC.exe, which is the offline shader compiler. You can run "FXC /?" to see the command line options.

I wrote a C# app which scans my shader files for information about ubershader options, etc, and then it launches FXC repeatedly with the appropriate options.