
Posts
417 
Joined

Last visited

Days Won
5
Everything posted by DanW58

A "psychic" shader mod; development begins...
DanW58 replied to DanW58's topic in Applications and Contributions
I have no idea what it looks like without glsl, and frankly ... I mean, the old OpenGL pipeline all it can do for water as far as I know is alphablend. Anyways, I just implemented the true Fresnel formula from Wikipedia, and got rid of Schlick's approximation, so it looks different yet again, but better. Now I have new bugs with my coastal wet look darkening hack; doesn't want to work anymore. I will post a new pyromod when I get it to work. 
A "psychic" shader mod; development begins...
DanW58 replied to DanW58's topic in Applications and Contributions
@nifa Sorry, when I said all graphics maxed out I wasn't thinking about FSAA and sharpening. I have sharpening disabled, and MSAA at (4x). (FSAA 16x may have been the cause of the out of memory) 
A "psychic" shader mod; development begins...
DanW58 replied to DanW58's topic in Applications and Contributions
@nifa Okay, here's the metal shader set version 0.1.1: (fingers crossed) Unfortunately, I don't get the problem so I can't tell if it is solved until you tell me. The "out of memory" error is worrisome... Not sure what that's about. And the second problem I don't understand. metal_shader_set_v1.1.pyromod 
A "psychic" shader mod; development begins...
DanW58 replied to DanW58's topic in Applications and Contributions
No, it's my bug. There's swizzling operators, in glsl, like for 2, 3, 4component vectors, you can write A = B.rgba or A= B.xyzw or A = B.stpg, for color, dimension or texture coordinates respectively. They all mean the same thing, but you cannot mix them, by the strict rules of glsl language, thus A = B.rgzw is illegal, but not every vendor enforces the rule. 
A "psychic" shader mod; development begins...
DanW58 replied to DanW58's topic in Applications and Contributions
Alright, I don't understand the second problem; I'm not sure where that is or what I'm looking at. This water_high.fs should solve the first problem; I post it here while I work on making a new pyromod. water_high.fs 
A "psychic" shader mod; development begins...
DanW58 replied to DanW58's topic in Applications and Contributions
Thanks; I think I can fix that; give me half hour or so. 
So, let's put Real Fresnel into code, assuming distinct indexes of refraction for the 3 colors for a give material, but assuming the index of refraction for air being 1 for simplicity. I'm returning reflectivity as well as cosines of refraction angles, as vec3's. Refraction sines will be good for refracted texture lookup's. Refraction cosines will be useful for iridescence calculations. const vec3 WHITE = vec3(1.0); void RealFresnel( float NdotL, vec3 IOR_RGB, out vec3 Frefl, inout vec3 sin_t, inout vec3 cos_t ) { vec3 Z2 = WHITE / IOR_RGB; // Assumes n1 = 1 thus Z1 = 1. vec3 cos_i = vec3( NdotL ); vec3 sin_i = sqrt( WHITE  cos_i*cos_i ); sin_t = min(WHITE, sin_i * Z2); // Outputs sin(refraction angle). cos_t = sqrt( WHITE  sin_t*sin_t ); // Outputs cos(refraction angle). vec3 Rs = (Z2*cos_icos_t) / (Z2*cos_i+cos_t); vec3 Rp = (Z2*cos_tcos_i) / (Z2*cos_t+cos_i); Frefl = mix( Rs*Rs, Rp*Rp, 0.5 ); // Outputs reflectivity. } Done! I'm going to test this in the water_high.fs shader... EDIT: Fresnel for sunlight entering the water, which is averaged (doesn't use wave normals) could be offloaded to the vertex shader.

Okay, I'm tracing the problem to Schlick's Approximation. Say we have a dielectric with a refractive index of 1; same as air. There should be NO reflection at any angle except maybe 90 degrees. But what does Schlick's hack say? R0 = ((n2n1)/(n2+n1))^2 ... (11)/(1+1) = 0 ... 0^2 = 0. So far so good; reflectivity at 0 degrees to the normal is 0. Reflectivity at any other angle is a different story ... refl = R0 + (1R0)*(1cos(a))^5 = 0 + (10) * (1cos(a))^5 = (1cos(a))^5 So, say a is 60 degrees, cos(a) = 0.5, 10.5 = 0.5, 0.5^5 = 0.03125; when it should be exactly zero. Small wonder, then, when I did this 20 years ago my Fresnel code was really complex, full of square roots... I was implementing real Fresnel back then for a reason, it seems. It's funny how foggy my memory seems. When I was researching stuff for this shader and I found Schlick's approximation, I thought I recognized it as what I had used 20 years ago; but for one thing: There were no square roots... I thought I remembered there being square roots in my original work. What to do? Schlick's hack is obviously garbage. Ok, here's from Wikipedia, real Fresnel starts with Snell's law, for refraction angle: Call the incident angle i and the refrated angle t, for editing purposes. n1 * sin(i) = n2 * sin(t) Remember what we care about is the cosines of these angles; but this is Snell's Law; period. So, sin(t) = (n1/n2)*sin(i) and sin^2 = 1cos^2, and viceversa, so we can compute cos(t) as cos(t) = sqrt( 1  sin(t) ) = = sqrt( 1  ( (n1/n2)*sin(i) )^2 ) = cos(t) = sqrt( 1  ( (n1/n2)* sqrt( 1(cos(i))^2 ) )^2 ) If we make n1=1 for air, cos(t) = sqrt( 1  ( (1/n2) * sqrt( 1(cos(i))^2 ) )^2 ) Then come the wave impedances: Z1 = Z0/n1 and Z2 = Z0/n2, where Z0 is the impedance of free space, but it cancels out in the final formula, so you can make it 1. So, Z1 = 1/n1 = 1 and Z2 = 1/n2 That's the easy part. Now come the Fresnel reflectivity formulas, for S and P polarizations, which can be averaged for nonpolarized light: Fresnel_reflectivity = ( Rs + Rp ) / 2, where, Rs = { [Z2*cos(i)Z1*cos(t)] / [Z2*cos(i)+Z1*cos(t)] }^2 Rp = { [Z2*cos(t)Z1*cos(i)] / [Z2*cos(t)+Z1*cos(i)] }^2 THAT is the Real Fresnel that I had implemented in a shader 20 years ago. Now it's coming back... But I remember also I was doing all this using vec3's, 3 calculations in parallel. I can't remember why, but may be that I was using distinct indexes of refraction for glass for the 3 colors. The index of refraction for materials changes with wavelength...

Thanks for the thoughtful feedback; I think defining just one region, "civilian" would suffice, and be optional. First of all, this could be exclusive to the less historically autocratic, more democratic civiliazations. So you are playing Athenians, say, and you can designate an area of terrain for civilian structures ahead of time, if you want. Otherwise, when the AI is ready to place a civilian building, it will place it wherever it wants. If the location is too inconvenient for your plans, you can still select the building and scuttle it. In terms of game balance, this could be made to be both good and bad. Good in that it could unlock technologies you won't find through normal buildings, perhaps; and it may produce food and build housing for you. On the other hand, it would increase the cost of materials and labor in general, which would manifest as buildings taking longer to build. For this to work, instead of the current paradigm of resources being enough to build something or not being enough, there should be a smooth interpolation between not enough and plentiful, where the interpolation applies to building speed. If you are too close to not having enough resources, building is possible but takes a long time; so it is better to have plenty more resources than are strictly necessary. With this paradigm change in place, resource consumption by civilian concerns can be a smooth and continuous issue. On the other hand, over time it selfadjusts, as high price of resources induces private mining startups. Although you could fear this would become a game that plays itself, consider that if larger maps are the future, and therefore longer games, the Mword ("micromanagement") can begin to be pronounced. So this would gradually relieve the problem as your population grows, so you can concentrate on military strategy.

The thing with dielectric layer over diffuse is that angle is not conserved across multiple bounces. Imagine, in the picture in the previous post, that we have incident light ray 'a', splitting same as before into a reflected 'b' and a refracted 'c'. However, ray 'd' will never happen: once 'c' hits the diffuse layer, it bounces off it in all directions spherically. Some of those rays may come out; some may reflect back in; and when those rays going back in hit the diffuse layer again, each of them will bounce back spherically again. We again have some kind of geometric series to solve, but the ratio of light going back in after each iteration is no longer connected to the original angle of incidence; it is only dependent on the base color and the index of refraction of the dielectric layer. The light that gets out gets out spherically; not specularly. This is interesting, because it means that an object with glossy paint does not reflect diffusely following the standard diffuse model at all. Only light that penetrates the dielectric layer can possibly bounce off the diffuse layer. Light coming at a shallow angle probably mostly bounces off specularly and never refracts in. So the intensity of the color reaching your eye is not proportional to dot(v_light,normal), but rather the square of that, or a polynomial of that. MUCH brighter towards the light source than a diffuse material. Furthermore, you are more likely to see more of the diffuse layer reflection the more aligned your view vector is to the surface normal. Why? Because photons bouncing off in the direction of the normal have a much greater chance of making it out of the dielectric layer than photons trying to come out at a shallow angle. For each index of refraction there must be an angle relative to the normal that photons coming out at that angle have a 5050 chance of making it out, or reflecting back in. Having that angle, I could use it as radius of a cone and calculate solid angle of light making it out versus reflecting back in. Okay, so, if R0 = ((n2n1)/(n2+n1))^2, we can calculate R0 for a number of refractive indices, then ask at what angle is the reflectivity = 0.5. We have, refl = R0 + (1R0)*(1cos(a))^5 (1R0)*(1cos(a))^5 = refl  R0 (1cos(a))^5 = (refl  R0) / (1  R0) 1  cos(a) = ( (reflR0) / (1R0) )^(1/5) cos(a) = 1  ( (reflR0) / (1R0) )^(1/5) a = acos( 1  ( (reflR0) / (1R0) )^(1/5) ); Let's make a little table: IOR n2n1/n2+n1 R0 reflRO 1R0 Div. root5 15rt deg. === ========= ===== ======= ===== ==== ===== ===== ==== 1.0 0.0 0.0 0.5 1.0 0.5 0.871 0.129 82.6 1.5 0.2 0.04 0.46 0.96 0.48 0.863 0.137 82.1 2.0 0.333 0.111 0.388 0.888 0.44 0.847 0.153 81.2 2.5 0.428 0.184 0.316 0.815 0.39 0.827 0.173 80.0 3.0 0.5 0.25 0.25 0.75 0.33 0.803 0.197 78.6 3.5 0.555 0.309 0.191 0.691 0.28 0.773 0.227 76.9 4.0 0.6 0.36 0.14 0.64 0.22 0.738 0.262 74.8 4.5 0.636 0.405 0.095 0.595 0.16 0.693 0.307 72.1 5.0 0.667 0.444 0.056 0.556 0.1 0.631 0.369 68.3 Well, there must be some kind of mistake. Angle at IOR 1.0 should be 90 degrees, and should be getting smaller faster as the index of refraction icreases. I'm too tired, though; going to bed. If you figure out my mistake, please post. Going backwards for the first row, IOR of 1, the result should be 90 degrees. That means, the cosine, or 1  fifthroot yada yada should be 0. So the fifth root yada yada should be 1. Fifth power of 1 is 1, so the division of (reflR0) by (1R0) should have given us 1; not 0.5 as it did. Now, 0.5 is the arbitrary reflectivity threshold I set; and this threshold should not matter in the case of IOR of 1; we should get 90 degrees for pretty much any reflectivity. Hrrrmmmmm.....

So, I was talking about Fresnel, and how to calculate the fraction going to diffuse, for a perfect car paint. (Everything else in the universe of shading dielectrics can be obtained by modifying the perfect car paint model.) What we want is to deduce how Fresnel should affect the base color below the transparent dielectric layer, taking multiple bounces into account. I deduced the math many years ago, but I don't have any records, so I'm doing it again even as I write these posts. Let me draw a picture: Okay, it took some time to draw that... NOTE: In the picture I say "here we assume diffuse", but the light bounces are showing specular trajectory. I thought diffuse was going to be easier to analyze first; but no; specular is easier, so we start with that. Starting at the bottom, we have a metal base (assuming it's a car body, but it could be terracotta, wood, or anything). Above it there's a diffuse OR specular color base; we'll tackle both. Above that there's the lacquer "gloss" layer, with a Refractive Index of 2 (glass is 1.5; water is 1.33), which I picked for no particular reason. Mathematicians like to abstract things; but I'm not a mathematician; I prefer to work with an actual exmple first; THEN abstract. Above that is the air, with a refractive index of 1.0000004 or whatever, pretty much 1.0, like vacuum. Assume 1. Top left corner is the Sun, or a light source, and a sunray coming down at 45 degrees. Schlick's approximation for amount of light reflected goes like... float SchlickApproximateReflectionCoefficient( vec3 ray, vec3 normal, float n1, float n2 ) { float rayDotNormal = dot( ray, normal ); float R0 = (n2  n1) / (n2 + n1); R0 = R0 * R0; //R0 is reflectivity at normal view float angle_part = pow( (1.0rayDotNormal), 5.0 ); return R0 + (1.0  R0) * angle_part; } So, let's do the math: If the light is coming at 45 degrees, rayDotNormal will be cos(45) = 0.7071. R0 =21 / 2+1 = 1/3; squared = 1/9. So, looking at this paint vertically, the gloss layer reflects 1/9th of the light; not enough to shave, unless the base diffuse color is black, such that it doesn't interfere with the reflection... The angle part is (10.7071)^5 = 0.29289322^5 = 0.002155. So we have 0.11111 + 0.88888 * 0.002155 = ... fresnel_reflection_factor = 0.1130271. This means our ray 'b', our Fresnel specular reflection has 11.3% of the strength of sunray 'a'. If we assume the light from the sun is RGB(1,1,1), ray 'b' has color b_RGB(0.113,0.113,0.113). The amount of light refracting into the clear lacquer layer is 1refl ... fresnel_refraction_factor= 0.8869729. So, ray 'c' has 88.7% of the strength of 'a', and therefore a color c_RGB(0.887,0.887,0.887); Now, let's assume the color layer is a sheet of gold, specular RGB(0.9, 0.8,0.5): ray 'd' will have a color of 'c' multiplied by gold's specular color, which turns into d_RGB(0.798,0.709,0.443). Here comes a big question: How much of d will reflect back as e, and how much will get out as f? You'll have to trust me on this one, because the angle is different, having refracted, AND the refractive indices of the two mediums is now reversed. However, I looked into this situation, did the whole math, and found that the reversing of the indices and the refraction angle all cancel out, and the reflectivity is the same for a mirror reflection of a refracted ray trying to refract out. Our calculation of reflection factor applies equally here: 11.3% will reflect down as 'e', and 88.7 will come out as 'f'. So, e will be d multiplied by 0.1130271, or e_RGB(0.09,0.08,0.05) ... pretty dark already. But 'f' coming out will be the difference, (de), or f_RGB(0.708,0.629,0.393). Let's continue: Ray 'e' now gets colored by the gold again, 'e'*gold, resulting g_RGB(0.081,0.064,0.025). Ray 'h' will be 11.3% of that, so h_RGB(0.0092,0.0072,0.0028). And ray 'i' is = gh = i_RGB(0.0718,0.0568,0.0222). My calculator is smoking... Now, the first reflection, b, I submit it is not part of the multibounce series; it is what we call the Fresnel specular reflection. We can ignore it, except for calculating c = ab. Then d = gold*c; then e = reflection_factor*d, and f=de. What we want to find out is the c to e and e to h ... ratio. c to d is gold's color; d to e is fresnel_reflectivity. So it is 0.113*(0.9,0.8,0.5) ... RRratio_RGB(0.1017,0.0904,0.0565), where RRratio stands for ReReflection ratio. What comes out, f, is a constant times e, namely fresnel refraction to reflection ratio. If fresnel refraction is 1reflection, then this ratio is (1/reflection)1. Since at each iteration we have an emerging ray at this ratio relative to the rereflected light, the total light coming out is this ratio times the total light rereflecting. So, at each iteration, rereflected light is RRratioRGB = refract_factor * specular_color. So the total light rereflected after infinite bounces is RRratioRGB^1 + RRratioRGB^2 + RRratioRGB^3 + ... This is solving an infinite geometric series. Where r meets the criteria −1 < r < 1, a + ar + ar2 + ar3 + ... = a/(1−r) So total_re_reflected_light = c_RGB / ( RGB(1,1,1)  RRratioRGB ) and the total emerging light (rays f, i, etc.) is that times ((1/fresnel_reflection)1) but since we don't care about the light that dies bouncing back and forth, we ONLY care about the light that we see, we can simply put the formulas together and say that, for the specular base case of specColRGB, we proceed as follows, in pseudoglsl now: void FresnelSplit( vec3 ray, vec3 normal, float n1, float n2, vec3 specColRGB, out vec3 bounce1, out vec3 bounceN ) { float raydotnormal = max( 0.0, dot( normalize(ray), normalize(normal)) ); float R0 = (n2n1)/(n2+n1); R0 = R0*R0; float angle_part = pow( 1.0  raydotnormal, 5 ); reflectivity = R0 + (1.0R0) * angle_part; bounce1 = vec3(reflectivity); float refractivity = 1.0  reflectivity; float RRratio = vec3(reflectivity) * specColRGB; vec3 dead_light = vec3(refractivity) / ( vec3(1.0)  RRratio ); bounceN = vec3((1.0/reflectivity)1.0) * dead_light; } BINGO! Next post I tackle Fresnel over diffuse, i.e. paint.

My work on the water_high.fs shader is done; and it is released as a mod together with the "metal shader" (metal and skin, really), and the terrain shader that reins in ultrabright textures and adds anisotropic ambient light. All of that as a package is available as a pyromod package in this forum post: The "water patch" is also updated by itself here: https://code.wildfiregames.com/D3603#157271 So, getting back to the new shader work, as I was saying many posts ago, what remains is really very little, and I'm going to include it below, though it's probably subject to change; none of this is compiling yet... // Main algorithm begins. vec3 incident_spec_RGBlight = incident_specular_light(v3_mod_normal,gndColor,Mat_RGB_diff,Obj_RGB_ao,RGBlight_bnormSky,Mat_SpecularPower,reflecting_ground ); vec3 fresnel_refl_color = SchlickApproximateReflectionCoefficient( is_metal, eyeDotNormal, 1.0, IndexOfRefraction ); vec3 incident_diff_RGBlight = incident_diffuse_light(gndColor,fresnel_refl_color,ao_color,aniso_amb,normal_hits_the_ground,rayDotNormal); vec3 color = specularly_reflected_light( Mat_RGB_spec, fresnel_refl_color, is_metal, incident_spec_RGBlight ); color = color + diffusely_reflected_light( Mat_RGB_diff, incident_diff_RGBlight ); // Main algorithm ends. #if USE_SPECULAR_MAP && USE_SELF_LIGHT color = mix(texdiffuse, color, specular.a); #endif color = applyFog(color); color *= getLOS(); gl_FragColor.rgb = mix(color,sqrt(color),1.0/3.0); // Regamma implicit degamma. } What I want to do next is dive deeply into the routines I never described or justified before. I call your attention to the fact that I have four functions that sort of work together. Two of them are for incoming light, namely incident_specular_light() and incident_diffuse_light(); and two "outcedent?" light returning functions, namely specularly_reflected_light() and diffusely_reflected_light(). These four functions are the heart of the shader. It is immensely useful to separate diffuse from specular completely, and it is even more useful to separate incident light RGB, material RGB reflectance, and reflected RGB light. Incident light multiplied by material color equals reflected light. You can add or mix light values; and you can mix or intermodulate reflective values; but you cannot mix or add a light and a reflectance, even if both are "RGB". This is why I like to tag my variable names with RGB or RGBlight... RGB alone stands for a reflectance, a material attribute, and its channels must span from 0.0 to 1.0, as materials can't reflect more light than what light hits them. But RGBlight values can go to the millions; there's no theoretical limit. Now, if you are not familiar with computer graphics, you might be asking "incoming specular?!?! ... Isn't light just light?". Yes: In the real world photons leave light sources and travel at the speed of light to meet their destiny by knocking an electron somewhere, and along the way get reflected diffusely or specularly, and they would not know the difference after it happened, never mind before. But a simulation of photons bouncing around is called a "photon mapper" and they are very good for some things, such as baking ambient illumination in complex scenes, but they make terrible solutions for realtime computer graphics. Heck, even slow and ponderous raytracers aren't photon mappers. What most computer graphics does is go the other way: from the eye to the light; yes, backwards. It is far cheaper to do so. And the difference between a realtime shader solution, and a slow raytracer, is basically the number and quality of bounces. Most real time graphics I would say computes "one point one bounces". First bounce being diffuse or specular. The second bounce is done where it is cheap to do by some humongous hack; and it is usually a diffuse second bounce from a diffuse first bounce; specularity be dammed. Add to that environment cubes and ambient occlusion bakes, and all together add up to about one tenth of a second bounce. Raytracers can go 7 bounces deep, if you are sure you'll live forever. But so we go from the eye, through the pixel in the screen we are rendering, into the virtual 3D scene, and hit the point on an object we are displaying currently. At that point we reflect this (backwards) "eye ray", bounce it off the object, as if it was a mirror, to see what direction we should reflect specularly. Once we know the direction, we can add up light coming from that direction; and that is what I mean by incident_specular_light(). Diffuse light coming to the eye from that point on the object does not need a reflection direction; it only needs to compute light arriving to that point from any directions, and how they angle relative to the surface normal. So, this sum of diffuse light from all directions is the incident_diffuse_light(). There's a few tricks to all this that very few shader programmers get right. For example, incident diffuse light includes environmental (ambient) light, and light from any light sources, typically the Sun. Now, say we have an algorithm to compute where shadows fall... those are computed from the Sun, so it makes sense to switch incident Sun light on and off as per the is_in_shadow() test; but it would make no sense to modulate ambient light by shadow test. That's not a mistake commonly done; but one mistake very commonly done is to modulate specular reflection by the shadow test, and that is a terrible mistake that looks awful, but few people can tell what's wrong with the rendering. Imagine you are in a room, looking at yourself on a mirror, and sunlight is hitting the mirror. Now your roommate comes and makes a shadow falling on the mirror. Does that affect your image on the mirror? Of course not; it is only if the shadow falls on you that your image in the mirror changes. Some shader programmers are careful about that, and yet fail to be careful about a deeper subltelty: It would be a mistake to say that the is_in_shadow() test has NO place in the specular pipeline. Why? Because the specular pipeline includes two things: Environment mapping, where you read the prebaked sky color that should be reflected, and Phong shading, where you add the Sun's reflection. The Sun's reflection will NOT be there if the point is in shadow. Another VERY tricky part is where the specular and diffuse pipelines sort of get joined at the hip, and that is with twolayer materials, such as paints, plastics, skin and green plant material. It may seem hopeless to try to separate them given that light that refracts into the transparent layer bounces off the underlying opaque material and then wants to come out again, but part of it is reflected back down, to bounce and be colored yet again by the opaque base. However, the multiple attempts at refracting back out can be accounted for by a single factor to multiply diffuse reflection by. In traditional Fresnel modelling of glossy paint, fresnel_reflection_factor = getFresnelReflectivity( ray, normal, n1, n2 ); fresnel_refraction_factor = 1.0  fresnel_reflection_factor; Most people leave it at that. What I do is, when I'm in a hurry, fresnel_refraction_factor = fresnel_refraction_factor * fresnel_refraction_factor; Why? Because it takes as much effort for light to refract out as it was to refract in, assuming a specular bounce, of course, but what better can we do? Well, we CAN do better by considering that light that bounces back in gets colored again by the diffuse color base, and makes another run for the surface; so you have an infinite series, and if you solve it it becomes a very simple fractional formula. For a simple example, 1 + 1/2 + 1/4 + 1/8 + 1/16 .... = Sum[x=0~inf]{ 1/2^x } = 2 But anyways, my point is that you CAN precalculate the fresnel factor for diffuse from a light source, as well as for diffuse from the environment map, and the two pipes don't need to exchange data between them. In the next posts I will discuss each of these four routines. Why? Just so that there is documentation on them somewhere to be found. Unlike C and C++, where you are encouraged (in most communities, anyways...) to write a lot of comments; in glsl you are not so encouraged, since the file is compiled on the fly, at runtime, by the videocard's driver. Too many comments would increase compile time.

I haven't read all 148 pages here, but a quick look reveals much interest in trading and deals and more complex interciv relationships. Here's an idea that might make a transition to more complex things easier: Implementing Free Market forces. Presently, your role as a player is as a (benevolent) dictator. You decide how many men and women will be born, and what their jobs will be. But just as there are currently "mercenaries" available, though they do not yet charge you money, like mercenaries would, by definition, but this could be fixed, you could also have entrepreneurial farmers that spring up when food is low (and presumably price is getting higher). The same could go for weapons production, training of mercenaries, and research. Doesn't have to be one way or the other; it could be a mix of government and private industry. And the mix might have a default number for each civilization, but be amenable to change through player actions. I'm not talking about a full economy; just about entrepreneurial, private industry actors vetting for government contracts, presumably. So, say, if you manually start a lot of farms, entrepreneurial farmers never happen; but if you let the food run low, then you see private farms popping up. Same for private barracks. Same for "research centers", which might be a new type of building where all the research that any other buildings can do is reflected all in one building, BUT where you cannot order what to research, it rather happens by itself, more slowly, but for free (they manage their own budget); or in the future you could pay a price to request a research direction. Also, these buildings could have hidden gems of technologies not available in any of the government buildings. Private houses could also pop up when food is plentiful.

Mayan buildings for 0.A.D (under development).
DanW58 replied to Lopess's topic in Game Modification
This is offtopic here, but it would be great to have most preColumbian American civilizations in a mod. Among them the Inca, who came up with advanced food preservation techniques for their defense. This could be a source of inspiration for expanding gameplay elements. The Inca had very mobile armies moving around "at random" along fronteer territories. The farmers in those regions were instructed to provide food for the armies by burying it in secret locations. It had to last until an army came around, so there were techniques that had to be observed to make sure the food kept fresh until then. I think they invented dry tomatoes and soups you just add water to. 
Update: As probably all of you know already, the landing of Perseverence was a complete success. Not that it was glitchfree... There are debris that come out with the parachute deploy that were not supposed to be there... Something broke off the spacecraft; probably not too important. Also, when the heatshield falls away, it carries with it a spring it wasn't supposed be carrying away with it, but no harm anyways. And how do we know all this? Because unlike previous missions, this one was programmed to take video of the whole descent and landing, and we have the video, and it's awsome. But it was supposed to also record sound, but the microphone failed. But the backup microphone is apparently working, and we got sound of Martian wind. Anyways, here's a video by this great science video youtuber, Anton, with a rough update of what's up with Perseverence: If you need to see the few things that went wrong with it, check out Scott Manley's video on it: And here's a longawaited update on Schroedinger's Cat, by Science babe Sabine: not that I agree; this "Superdeterminism" stuff sounds like a joke to me. Why do people keep trying to come up with new "interpretations" when Bell's Theorem already *proved* there's no need for anything beyond what QM equations describe?

A "psychic" shader mod; development begins...
DanW58 replied to DanW58's topic in Applications and Contributions
Great! Thanks for all the patience, and enjoy. This set has the latest water shader in it. 
A "psychic" shader mod; development begins...
DanW58 replied to DanW58's topic in Applications and Contributions
Okay, I think I got it; hope it works. Includes metal and skin detection. Metal is enhanced by matching hue of diffuse and specular and ensuring that diffuse saturation is higher than specular's, but not much higher; and that specular value is higher than diffuse. Skin is enhanced by adding partial Fresnel specularity to it, of low gloss (skin is colored in diffuse, but shimmerreflects white), and by adding a hack to make it seem like it gives a hint of red translucency. Unfortunately, skin and metal are very hard to distinguish by color, and sometimes they cross into each other. Also, patches of grass and other things may detect as skin, or as metal; but they don't look bad; just a bit shinier than they should be. Something no other shader has is a megahack to compute specular occlusion. That is, figure out if a sight ray reflecting off a shiny surface should reflect sky, or an object nearby. The common wisdom is that you need real time raytracing to get specular occlusion. Well, I got it to work based on the baked ambient occlusion. If you look at shiny pots or shields inside shady patios, you can see a limited reflection of sky on them that keeps facing you as you turn around the building. Also included is the latest water shader, with more realistic Fresnel specular and refractive factors, and with a hack to make coasts look wet. The terrains shader detects soils or tilings that are too white, and tones them down while increasing contrast. Ambient occlusion (ambient light selfshadowing) of buildings is better displayed. The material xml files are changed, in fact, to standardize the gain for ambient occlusion bakings to 1.0, rather than have manually adjusted gains everywhere. Also in the terrains shader there is a bluetinted upward bias on ambient light, as most ambient light comes from above, and has a blue tint due to atmospheric scattering. For perspective, there are many shaders out there that do things like Fresnel; specular highlights, environment mapping and whatnot; however, they need to be told, via textures, what to do. The peculiar thing about this metal and skin shader is that it figures out what to do without being told... It's a way to enjoy a tiny hint of what will be coming next, without the work of adding new textures and all that. If there's any problems, shader not compiling, whatever, please report it to this thread. You may need to turn all the graphics options to maximum; I haven't even tested it nonmaxedout. metal_shader_set.pyromod 
A "psychic" shader mod; development begins...
DanW58 replied to DanW58's topic in Applications and Contributions
I'm using Linux, but I'm an eternal newbie at it. The only thing I hate more than Linux is Microsoft; that's how I'm here. Okay; what I'm trying to find out is how to create a mod; not how to unzip one. I'm having a hard time persuading all these archiving tools to keep the filepaths when adding to a zip. 
A "psychic" shader mod; development begins...
DanW58 replied to DanW58's topic in Applications and Contributions
Sorry, Sarcoma; I've no idea what that means. 
A "psychic" shader mod; development begins...
DanW58 replied to DanW58's topic in Applications and Contributions
Thanks, guys, but I'm having a breakdown here. I did everything as you guys said. I created a test folder. Extracted Stan's zip; it created dan_shaders folder with a shaders subfolder and a glsl subsubfolder. I replaced all 4 files with latest versions. I added the art/materials folder, with all the xml files. Opened Stan's zip file again with PeaZip, went to AddFile, added all the files, saved. Then open the result with ArchiveManager and it wants to unzip all the files in the one subfolder. This stuff is INSANE to try to understand. 
A "psychic" shader mod; development begins...
DanW58 replied to DanW58's topic in Applications and Contributions
Not working for me. Even using Stan's file; I place it into a test folder, but it creates a "dan_shaders" folder. Even if I rightclick and say "Extract Here"; no matter, it always creates a stupid subfolder. 
A "psychic" shader mod; development begins...
DanW58 replied to DanW58's topic in Applications and Contributions
Ahhh, I'm going to try this. Many thanks. 
A "psychic" shader mod; development begins...
DanW58 replied to DanW58's topic in Applications and Contributions
Man, why does life have to be so difficult? Archive Manager AND Ark BOTH have no option for keeping the folder structure. Then Xarchiver has two options: Full path, or NO path; no option for relative path; and it crashes anyways; tells me to check some viewing option to see the error, which viewing option is nowhere to be found. Linux coders, 90% of them, seem bent on pushing people away from using the OS; they boobytrap everything they do. How do you make this zip file, Stan? EDIT: Spent like two hours searching the internet for what's a good archive manager; and they all agreed it is PeaZip. Had to install a special installer to get it installed. Full of options, but I specified to keep paths of the files; but when I test the file it extracts everything in a folder it creates by the name of the zip file. There's no end to suffering... 
A "psychic" shader mod; development begins...
DanW58 replied to DanW58's topic in Applications and Contributions
SUCCESS!!!! Kind of ... Got the coasts to look wet. But the artifact I wrote about in the previous post is still there. 
A "psychic" shader mod; development begins...
DanW58 replied to DanW58's topic in Applications and Contributions
Cool! So glad to hear! In the meantime I'm still hacking the high water shader (water_high.fs) ;) Managed to hide the repeating tiles of the waves by mixing the wave pattern with different scalings and rotations. I also got rid of the terrible artifacts I was getting on land; it was just a funny constant in the Fresnel approximation routine that is supposed to be 1.0 but anything less than 1.12 causes those artifacts. Now I have 1 artifact left at a distance, which this funny constant doesn't fix...