Jump to content

Modding Textures EDIT: and Shaders


Lindor

Recommended Posts

  1. Search the texture and surface.txt entry
  2. change them
  3. load ingame or into grannyviewer
  4. it looks completely different from what you expected
  5. repeat from step 2

This is no fun. No wonder I make no progress with my mod. Scripting is just so much more fun and result-yielding. I'm just searching for excuses to not work on my textures. I wish there was a way to directly edit the surface at the model. I want to see how it looks ingame WHILE I'm retexturing. Including everything surface.txt does with the flags and shaders. Is it possibe? Can you help me with that?

Do I really have to go to dirty untrustworthy websites to get a more or less legal version of 3ds max 8? I don't want to do that. And buying? Haha no. Even if I had the money. Not in a million years will I spend that much money on a 3d modelling software while blender exists just because companies these days didn't like modders. Why does this crypto-like format even exist? Who thought that would be a good idea? Pls help.

Edited by Lindor
Link to comment
49 minutes ago, Flix said:

It takes time and patience to learn how saturation and hue will translate when rendered, not to mention the dramatic effects that the sg maps can have.

Is there even something to learn? To me, it feels like utter chaos.

I always thought that I'm not a visual artist, by any means. I can't draw. The best pictures I've ever created are the thumbnails of my Skyrim mods, there I learned that even I can do visual art. But Sacred 2 simply does not want to cooperate. I don't feel like it's on me, I feel like the standard way of doing it is just not good. The cycle I described above: it's not fun, you can't see the effect your editing has ingame until it's too late, sometimes the 2d mapping to the 3d model is SO CHAOTIC (-> Deylen helmet) and there's absolutely no learning effect. I want to edit the texture at the model directly. This would make sense. Right now it's just a guessing game.

49 minutes ago, Flix said:

And even this final result feels so amateurish to me nowadays that I recreated it from scratch recently, and it took perhaps one afternoon session:

jQLFsG3.jpg

Honestly? I like the left one much more, it's not even close. Right just looks like something taken straight out of the Borderlands game. Textile and leather are supposed to be irregular and a little bit dirty. But I guess it's taste in the end.

Edited by Lindor
  • Like! 1
Link to comment

Now here's an issue I have:

I'm somewhat fascinated by starry textures

On 1/18/2022 at 3:21 AM, Lindor said:

Inspiration were the Diablo 3 Galactic Wings, that's also why I chose the green fad-in. But I'm thinking about making them purple :)

Cosmic Wngs:

222ECC4B57DAB86F3A

Galactic Wings:

PersonalScarceCoypu-max-1mb.gif

You see, there's a really cool rendering effect happening while moving with these Wings, it really feels like an open gate to space and cosmos. THIS is what I envision.
I think the closest Sacred 2 has is the crystal shader, not sure, nevertheless I tried and you all know the results:

BfP71yf.jpeg

It doesn't work. And that is the best I could come up with amongst hundreds if not thousands of different versions. Absolutely horrible.
But you see, I'm not the only one with that problem though. Sopor Aethernis e.g. is supposed to be starry as well. It actually looks kinda OK-ish in the character menu:

JRY2bpn.jpeg

However that doesn't tell the real story. Look at this leg:

pSxOIdt.jpeg

What is this? Absolutely no depth. Flat, flubbery and distorted! Where is the depth effect we desire? It looks like colorized pantyhose tights.

 

The real Problem is triggering the different shader effects. The fx7 shader e.g. only works on somewhat smooth gradients. The crystal effect is controlled by the glow map, but it only works for big enough "sections" again. Space however is made of hundreds of layers of super small stars, it is not possible to divide it into different big sections unless you have a very small amount of very large stars. I wish there was a way to lay multiple surfaces on the same part of the same model, then we could have the dark blue background space controlled by the fx7 shader, some nebulas in a surface in front and then multiple surfaces of stars with crystal shader in front. But I'm not even sure if that would work.

The shaders are simply suuuper sensitive to the colors. One pixel off, and the whole shader stops working. The best example is the lava shader, I'm still trying to figure out how to properly use that without the whole thing just becoming outright red.

And I haven't even talked aout the biggest problem yet: The mapping of the the Deylen helmet is an absolute nightmare, and all the other pieces aren't easy to figure out either. I feel absolutely cursed here, not being able to retexture directly at the model and instead guessing where each section is... it's not good.

The thing is that the game does not let me freely do what I envision. It puts limit after limit. There are people who think limiting options would enhance creativity. I don't. It's so bad that I'm actually thinking that this right here:

17 hours ago, dimitrius154 said:

That would require to completely rewrite and recompile s2render.dll.

would be more result yielding AND quicker than to work with what we got, even though it would take forever.

There is one last hope I have, which is doing something similar to what has been done to blueprint.txt: A thread where the leading post explains in detail what each shader and flag in surface.txt is doing including their limitations, the information comes from people sharing their knowledge in the thread.

Link to comment
53 minutes ago, Lindor said:

Flat, flubbery and distorted! Where is the depth effect we desire? It looks like colorized pantyhose tights.

The ugliness of the Communitypatch Sets is the main reason I never wanted to play it.

Maybe as a start you could change the _sg files to add some glow to the stars on the... leggings. That should make the stars look a bit less like someone took a space google image and pasted it on it as the new texture.

Link to comment
1 hour ago, Lindor said:

The best example is the lava shader, I'm still trying to figure out how to properly use that without the whole thing just becoming outright red.

For the lava shader you can use any texture you want as the texture3Name.  That's why EE has blight, eldritch, bloodlust, and ghostly in the hq/fx folder (this was Dmitriy's idea).  You could sub in something else entirely.  You might have some luck getting the illusion of movement that way.

The more opaque the alpha channel in the sg map, the more intense the lava effect. This also supersedes/diminishes the emissive glow however.

Link to comment
2 hours ago, dimitrius154 said:

Hmm, try decreasing opacity via lowering the diffuse texture's alpha channel brightness.

Well it seemed to have potential when I tried it with my original design, although it didn't help with the glow map, at least the diffuse map now got the same effect you can see on the spider armor.
I tried following this cool tutorial and combining it with your tip: 

xhwdnrf.jpeg

It doesn't want to work, the picture looks beautiful, but always something goes wrong no matter how I choose the glow/diffuse maps, one always steals the show.:dntknw:

1 hour ago, Vishanka said:

The ugliness of the Communitypatch Sets is the main reason I never wanted to play it.

Maybe as a start you could change the _sg files to add some glow to the stars on the... leggings. That should make the stars look a bit less like someone took a space google image and pasted it on it as the new texture.

Agreed! It's on my, uhm, five sites long to-do-list on my desktop. Which has been sitting there for years, not stopping to grow.

But CM has also some nice looking stuff to offer, the nine hells set e.g. looks pretty decent imho. Or the HE mutation set, but credits there go to the original devs, CM simply unlocked it AFAIK.

1 hour ago, Flix said:

The more opaque the alpha channel in the sg map, the more intense the lava effect. This also supersedes/diminishes the emissive glow however.

Aaaah. Thx for the info Flix, will be added to the surface.txt thread:thumbsupsmiley:

Link to comment
4 hours ago, Lindor said:

.Thx for the info Flix, will be added to the surface.txt thread

Therefore, it's the diffuse + specular glow. To be expected. Also, some buff special effects add to the confusion.

Then again, one should remember, that the game's engine is effectively older, then the first Mass Effect.

Link to comment
  • 3 weeks later...

The effect of the scorpion shield/nature magic dryad buff, FX_SC_SCHILD, looks like something promising. Now this is a visual effect and not a surface, but it looks like surface functions could maybe be used by these fx. If they're pointing to a specific surface.txt shader and/or flags in s2render.dll, that would be great. Unfortunately, these fx don't have a particle script. Interesting files are:

pak/graphics25/hq/fx/skorpionshield.dds
pak/graphics13/hq/fx/skorpionshield.dds
pak/graphics01/hq/fx/skorpionshield2.dds
pak/graphics01/hq/fx/skorpionshield.dds

None of which are mentioned anywhere in surface.txt, unfortunately. So in the end what's left is searching the dlls with ollydbg for any mentions of these fx and it's files, and I'm really bad this. I'm afraid to ask this, but can someone do a little search for me, please? But do not waste your time if it takes too long, in the end it's just a hope, a suspicion. There's no evidence whatsoever that the fx use a surface.txt shader/flags other than the way it works and looks ingame.

Link to comment
  • 4 weeks later...

Info: It is possible to script your own shader at the beginning of the file!

I'm getting closer. Somewhat.

K2t6LcY.jpeg

Look only at the torsoes. Left uses fx6, middle uses crystal and right uses a custom shader:

XXXXX = {
  diffusePnt    = "object/diffVelvetPnt.shader",
  diffusePntShd = "object/diffVelvetPnt.shader",
  z             = "object/z.shader",
  shadowmap     = "object/shadowMap.shader",
  cubeshadowmap = "object/cubeShadowMap.shader",
  ambDiff       = "object/ambDiffPulse.shader",
}

It is super hard, but I'm getting there. Slowly.

  • Respect! 1
Link to comment
  • 1 month later...

I have learned how the original Inquisitor's Astute Supremacy Set's shader's refletion works. It's using a technique called "Skyboxing".

The Skybox is not dependent on the textures you input! This is how the skybox looks mapped at the creatures without any additional calculations done:

3a9T7NI.jpeg

The Skybox is calculated around the player character (more accurately: the camera's view center) and NOT the object! This is why you can't use it on characters with energy shields or it'll look like this:

eRYuSp8.jpeg

Also underwater is wierd: It gets black as well, however if you're making a screenshot for a split second it goes back to normal:

3WnlfnC.jpeg

I was able to trick the system however, this is how it actually looks:

SouvlH3.jpeg

And here are some more screenshots:

GOzTTiW.jpeg

eQ8iZ6z.jpeg

hiIERJp.jpeg

Kinda metallic isn't it?

 

I still have no idea why the fx7 shader only works on smooth gradient-like textures, but I can assure you it's not the reflection effect! It has to do smth with the texcoords I think.

Edited by Lindor
Link to comment
  • The title was changed to Modding Textures EDIT: and Shaders
20 hours ago, Dax said:

Hehe. The boar has the same facial expression like my dog when he did something wrong. Even the tongue is out a bit!

:lol:

bull terrier! 

There is two walked regularly on our street 

:)

gogo

Link to comment
22 hours ago, Lindor said:

Ladies and gentleman, I did it!

I managed to transform the texcoords into screen space and made it so that it resizes with the camera distance. So the textures are now independent of the model, there's no mapping anymor. Which is exactly the effect of D3's Cosmic/Galactic Wings I desire so much. Trust me, it was an insane amount of work!

I've taken the wobbly effect from the fx6 shader e.g. used for the Saraki's path to the netherworld set, glow is dependent on the wobbly texture's brightness so that the stars light up when they're hit by the wobbly area.

 

This is how it looks in the main menu:

rTLveYL.gif

And this ingame:

95h7bdC.gif

A little bit pixelish and sped up due to the GIF conversion process, but I hope you get the idea.

Ideally this isn't the final version since I want to make it a little bit brighter first, but I don't know how possible that is without destroying everything.

@VishankaIf I remember correctly, you were interested into this as well. What do you think?

 

To anyone interested, this is my code:

  Reveal hidden contents

It's a little bit messy, not all leftovers are cleaned and it misses commentary, but there's not a single unnecessary line of actual code, it's pretty much good to go. Just hard to understand.

beautiful effect with the robes.. and the zoom you pulled off makes it magnetic approach, good drama lindor.

gonna show it to Schot, maybe there's also an idea here for default avatars for DarkMatters when new members register?

:thumbsup:

gogo

  • Thanks! 1
Link to comment

Final version of the shader. To me it looks like 10x better, but in actuality it's probably like 1% improvement for a whole day of work on it. No GIF today because too much gets lost during conversion process.

y7eJ2tR.jpeg

Shader Code:
(now cleaned up and with commentary to make it understandable)

Spoiler
// ambient
#include "extractvalues.shader"
#define LIGHTBLOCKS 4

struct appdata {
	float3 position     : POSITION;
	float3 normal       : NORMAL;
	float3 tangent      : TANGENT;
	float3 binormal     : BINORMAL;
	float2 texcoord     : TEXCOORD0;
	float2 data         : TEXCOORD1;
};

struct pixdata {
	float4 hposition    : POSITION;
	float4 texcoord0    : TEXCOORD0;
	float4 surfNrm_ws   : TEXCOORD1;
	float4 lightNrm_ws  : TEXCOORD2;
	float4 camDist_ws   : TEXCOORD3;
	float4 screenCoord  : TEXCOORD4;
};

#ifdef SM1_1
struct fragout {
	float4 col         : COLOR;
};
#else
struct fragout {
	float4 col[2]      : COLOR;
};
#endif

pixdata mainVS(appdata I,
	uniform float4x4 worldViewProjMatrix,
	uniform float4x4 worldMatrix,
	uniform float4   light_pos,
	uniform float4   camera_pos)
{
	pixdata O;
	
	// vertex pos
		float4 pos4 = float4(I.position.xyz, 1.0);
		float4 nrm4 = float4(I.normal, 0.0);
		O.hposition = mul(pos4, worldViewProjMatrix);
	
	// lighting
		O.surfNrm_ws = mul(nrm4, worldMatrix);
		O.lightNrm_ws = normalize(light_pos);
		O.camDist_ws = camera_pos - mul(pos4, worldMatrix);
		
		float c_dist_ws = sqrt(dot(O.camDist_ws.xyz, O.camDist_ws.xyz));
	
	// pass texture coords. THIS IS WHERE THE MAGIC HAPPENS!
		float4 halfway = calcScreenToTexCoord(O.hposition);
		O.screenCoord = halfway;
		float resolution = 0.05 * c_dist_ws;
		O.texcoord0 = float4(((halfway.x / halfway.w) - 0.5) * resolution, ((halfway.y / halfway.w) - 0.5) * resolution, halfway.z * resolution, halfway.w * resolution);

	return O;
}

fragout mainPS(pixdata I,
	uniform sampler2D   texture0,
	uniform sampler2D   texture1,
	uniform sampler2D   texture2,
    uniform sampler2D   shadow_texture,
	uniform samplerCUBE textureCube,
	uniform float4      system_data)
{
	fragout O;

#ifdef SM1_1
	s2half4 tex0 = tex2D(texture0, I.texcoord0.xy);
	O.col = float4(tex0.xyz, 1.0);
#else
	float time = system_data.x;

	s2half4 tex0 = tex2D(texture0, I.texcoord0.xy);
	s2half4 shadow = tex2Dproj(shadow_texture, I.screenCoord);

  //take the wobbly effect from the fx6 shader (it's called "fx6" in surface.txt, but the shader is called "ambDiffFx5.shader")
	float4 sum_color = float4(0.0, 0.0, 0.0, 0.0);
	float I = 0, sum_num = 6;
	for(I = 0; I < sum_num; I++)
	{
		float2 offsetUV = I.texcoord0.xy / 7.0;
	  //make it a little bit slower than in fx6
		offsetUV.y += frac(0.55 + 0.3375 * I * time / sum_num + 0.15 + I / sum_num);
		s2half4 wave_offset = tex2D(texture2, offsetUV);
		float h_offs = (I / sum_num) + (0.1 + 0.03 * I / sum_num) * (wave_offset.x - 0.5);

		offsetUV = I.texcoord0.xy / 7.0;
		wave_offset = tex2D(texture2, offsetUV);
		float v_offs = (0.3 * I / sum_num) * wave_offset.z * (wave_offset.y - 0.5);

	// calc lookup
		float2 newUV = I.texcoord0.xy / 7.0;
		newUV += float2(h_offs, v_offs);

	// fx base color
		s2half4 base_color = tex2D(texture1, newUV);

		base_color = pow(base_color, 1.0 + 2.0 * wave_offset.x + 2.0 * wave_offset.y);

		sum_color += base_color;
	}

	sum_color /= sum_num;
  //end of fx6's wobbly effect calculation, begin of my own color tweaks for the wobbly texture
	float brightness_sum_old = sqrt(dot(sum_color.xyz, sum_color.xyz) / 3);
		
	// convert rgb into hsl -> set s=1.0 and l=0.5 -> convert back to rgb
	// trick: HSL colors of kind (hue, 1.0, 0.5) have always one color equal 0.0 and one equal 1.0 in rgb. Just keep the ratios between low, mid and high rgb value constant.
		if (sum_color.y <= sum_color.z) {
			if (sum_color.x <= sum_color.y) {
				float low = sum_color.x;
				float mid = sum_color.y;
				float high = sum_color.z;

			//avoid dividing by 0
				mid = low / (1.0001f + low - high);
				low = 0.0;
				high = 1.0;

				sum_color.x = low;
				sum_color.y = mid;
				sum_color.z = high;
			}
			else {
				if (sum_color.x <= sum_color.z) {
					float low = sum_color.y;
					float mid = sum_color.x;
					float high = sum_color.z;

					mid = low / (1.0001f + low - high);
					low = 0.0;
					high = 1.0;

					sum_color.y = low;
					sum_color.x = mid;
					sum_color.z = high;
					}
				else {
					float low = sum_color.y;
					float mid = sum_color.z;
					float high = sum_color.x;

					mid = low / (1.0001f + low - high);
					low = 0.0;
					high = 1.0;

					sum_color.y = low;
					sum_color.z = mid;
					sum_color.x = high;
				}
			}
		}
		else {
			if (sum_color.x <= sum_color.z) {
				float low = sum_color.x;
				float mid = sum_color.z;
				float high = sum_color.y;

				mid = low / (1.0001f + low - high);
				low = 0.0;
				high = 1.0;

				sum_color.x = low;
				sum_color.z = mid;
				sum_color.y = high;
			}
			else {
				if (sum_color.x <= sum_color.y) {
					float low = sum_color.z;
					float mid = sum_color.x;
					float high = sum_color.y;

					mid = low / (1.0001f + low - high);
					low = 0.0;
					high = 1.0;

					sum_color.z = low;
					sum_color.x = mid;
					sum_color.y = high;
				}
				else {
					float low = sum_color.z;
					float mid = sum_color.y;
					float high = sum_color.x;

					mid = low / (1.0001f + low - high);
					low = 0.0;
					high = 1.0;

					sum_color.z = low;
					sum_color.y = mid;
					sum_color.x = high;
				}
			}
		}

		float brightness_sum_new = sqrt(dot(sum_color.xyz, sum_color.xyz) / 3);
	  //pre-converted brightness is very dark
		brightness_sum_old *= 5.0;
	  //and finally, swap new brightness for old one so it doesn't get max brightness everywhere.
		if (brightness_sum_old < brightness_sum_new) {
			sum_color *= (brightness_sum_old / brightness_sum_new);
			brightness_sum_new = brightness_sum_old;
		}

	  //end of wobbly texture magic, begin of starry texture magic
		float brightness_tex0 = sqrt(dot(tex0.xyz, tex0.xyz) / 3);
	  //convert rgb into hsl to get the saturation
		float max_tex0 = max(tex0.x, max(tex0.y, tex0.z));
		float min_tex0 = min(tex0.x, min(tex0.y, tex0.z));
		float lightness_tex0 = 0.5 * (max_tex0 + min_tex0);
		float chroma_tex0 = max_tex0 - min_tex0;
		float saturation_tex0 = 0.0;
		if (abs(lightness_tex0 - 0.5) < 0.49f) {
			saturation_tex0 = chroma_tex0 / (1.0 - abs(2.0 * lightness_tex0 - 1.0));
		}
		
	  //compose wobbly+starry. saturation is necessary so that the stars don't get overlayed with the wobbly.
		float lerpval = saturation_tex0 * (0.5 + 0.5 * (brightness_sum_new - brightness_tex0));
		float4 final_col = lerp(tex0, sum_color, lerpval);

	  //calc glow. Make stars glow as shiny as possible whenever they get "hit" by the wobbly texture. Make nebula (wobbly texture) glow a little bit. Make everything else only glow very slightly to not make it too dark.
		float glow_alpha = saturate(0.01 + 2.0 * ((1.0 - saturation_tex0) + 0.2) * brightness_sum_new);
		float4 final_glow = final_col * glow_alpha;

	  //and ready to go
		O.col[0] = float4(final_col.xyz, tex0.w);
		O.col[1] = float4(final_glow.xyz, glow_alpha);
#endif

	return O;
} 

 

Surface.txt code:

fxTEST = {
  diffusePnt    = "null.shader", //You can add something here if you want to, like the velvet shader. Only makes sense if you plan making the fx transparent.
  diffusePntShd = "null.shader", //You can add something here if you want to, like the velvet shader. Only makes sense if you plan making the fx transparent.
  z             = "object/z.shader", //always needs to be the same
  shadowmap     = "object/shadowMap.shader", //always needs to be the same
  cubeshadowmap = "object/cubeShadowMap.shader", //always needs to be the same
  ambDiff       = "object/fx/ambDiffFxTest.shader", //whis is how I named the shader and where I put it. You have to put it in the correct folder inside shader.zip/unified.
}

 

Example surface:

newSurface = {
  name         = "in-armageddon-torso_s",
  texture0Name = "maps/heroes/inquisitor/sets/armageddon/TEST.tga", //starry texture
  texture1Name = "maps/heroes/inquisitor/sets/armageddon/s_inquisitor-armageddon-chest_sg.tga", //wobbly texture
  texture2Name = "maps/heroes/inquisitor/sets/scourge/s_inq_scourge_fx2.tga", //this needs to always be the same
  flags        = SURFACE_FLAG_OPAQUE,
  shader       = fxTEST,
}
mgr.surfCreate(newSurface);

Edited by Lindor
Link to comment

I know I said this would be the final version of the shader, but it still doesn't quite look as I wish. 

This is the texture I'm using for the starry background:
 

p1Fqryk.jpeg

Actually a lot gets lost with the .jpg transformation, it's very much brighter and purplier in .dds. I tried to upload it as .bmp, shareX automatically converts it to .png:

VxixllG.png
Still not perfect, but a lot closer to what it looks like in .dds.

Apply it to the model and it suddenly gets super dark instead of the purple background:

crYdzsu.jpeg

I've tried to correct this in the shader, but I fail to do it the way I want it to look. I wish the non-nebula'ed background was a little bit brighter, more purple and with more very tiny stars, kinda like a purple noise. The whole thing gets complicated by my efforts to make the stars shine and glow only when they're hit by the nebula, so the non-nebula'ed version is supposed to be brighter, noisier and purplier but not too much so you can see the difference to the glowing nebula'ed stars.

These are my attempts, left is the version I said would be final and right two are my attempts to correct:

UoMSV25.jpeg

It's a little bit better, but still far from what I envision.

@Flix @dimitrius154 @Vishanka I need your threes texturing experience. Is my texture too dark? Or is it the shader?

Link to comment
1 hour ago, Lindor said:

I need your threes texturing experience. Is my texture too dark? Or is it the shader?

Interesting, you're getting the RGB spectral diffusion. I'd advise lightening the dark parts and darkening the rest. 

  • Thanks! 1
Link to comment
2 hours ago, dimitrius154 said:

Interesting, you're getting the RGB spectral diffusion. I'd advise lightening the dark parts and darkening the rest. 

^ This.  Adjust the levels to bring the dark and light closer together since they're too far apart now.

My other thought was that the UV mapping on the model could be retooled. It looks like your source texture is getting squished down to a very small size and then tiled across the surface.  The smaller details get lost.

  • Thanks! 1
Link to comment

Sirs, you two are genii!

Thx for help! I have five different goals, and I've had 28 different tries since my last post. I'm gonna upload the try which suited best for each goal:

  • Nebula keeps original color
    Spoiler

    tZTGcg1.png

     

  • Nebula gets layed over everything that is not a star
    Spoiler

    jcjT4fa.jpeg

     

  • Stars only light up (very brightly) when they're inside nebula
    (This is by far the hardest goal, hence why this is also my latest attempt)
    Spoiler

    ZCFMYWH.png

     

  • nebula glows a little bit
    Spoiler

    HM7Oe9o.jpeg

     

  • all non-nebula'ed regions don't glow but have visible strry purple details
    Spoiler

    cq6UYwC.jpeg

 

I want all five goals at once. I have created five different additional textures, which one you think I should use? Or ar all five bad?

Spoiler

VxixllG.pngGzxKKVI.pngGXEEKyX.pngKzY1ms4.pngMSE9Fq4.pngDUmycZs.png

(first one is original from post above)

 

3 hours ago, Flix said:

My other thought was that the UV mapping on the model could be retooled. It looks like your source texture is getting squished down to a very small size and then tiled across the surface.  The smaller details get lost.

Great idea, the starry texture has actually 7x the resolution of the nevula. Problem is that this is necessary because otherwise this happens:

Spoiler

WxTYRdJ.jpeg

Same as with the leggins effect from the seraphim quite a couple of posts above. The details also get lost no matter what.

Edited by Lindor
Link to comment

It has taken me an absolutely enormous effort, but I've finally managed to make it look exactly the way I want it to! Final shader contains all kinds of goodies including gamma correction! Here's how it looks like:

XQusLc3.jpeg

@Flix @dimitrius154 thx for help again, your tip with adjusting the texture's brightness was worth pure gold! I ended up using this picure:

Spoiler

GXEEKyX.png

And here is a little evolution of the six previous versions of the shader, just so you see how tiny the amount improvement per step is:

Spoiler

nrwdjb3.jpeg

Last but not least, the golden heart of the countless hours of work, the shader itself, cleaned up and with commentary, free for everyone who wants to use it or just wants to see how it works:
(for surface.txt usage see example in my post above)

Spoiler
// ambient
#include "extractvalues.shader"
#define LIGHTBLOCKS 4

struct appdata {
	float3 position     : POSITION;
	float3 normal       : NORMAL;
	float3 tangent      : TANGENT;
	float3 binormal     : BINORMAL;
	float2 texcoord     : TEXCOORD0;
	float2 data         : TEXCOORD1;
};

struct pixdata {
	float4 hposition    : POSITION;
	float4 texcoord0    : TEXCOORD0;
	float4 surfNrm_ws   : TEXCOORD1;
	float4 lightNrm_ws  : TEXCOORD2;
	float4 camDist_ws   : TEXCOORD3;
	float4 screenCoord  : TEXCOORD4;
};

#ifdef SM1_1
struct fragout {
	float4 col         : COLOR;
};
#else
struct fragout {
	float4 col[2]      : COLOR;
};
#endif

pixdata mainVS(appdata I,
	uniform float4x4 worldViewProjMatrix,
	uniform float4x4 worldMatrix,
	uniform float4   light_pos,
	uniform float4   camera_pos)
{
	pixdata O;
	
	// vertex pos
		float4 pos4 = float4(I.position.xyz, 1.0);
		float4 nrm4 = float4(I.normal, 0.0);
		O.hposition = mul(pos4, worldViewProjMatrix);
	
	// lighting
		O.surfNrm_ws = mul(nrm4, worldMatrix);
		O.lightNrm_ws = normalize(light_pos);
		O.camDist_ws = camera_pos - mul(pos4, worldMatrix);
		
		float c_dist_ws = sqrt(dot(O.camDist_ws.xyz, O.camDist_ws.xyz));
	
	// pass texture coords
		float4 halfway = calcScreenToTexCoord(O.hposition);
		O.screenCoord = halfway;
		float resolution = 0.05 * c_dist_ws;
		//float resolution = 0.01 * c_dist_ws;
		O.texcoord0 = float4(((halfway.x / halfway.w) - 0.5) * resolution, ((halfway.y / halfway.w) - 0.5) * resolution, halfway.z * resolution, halfway.w * resolution);

	return O;
}

fragout mainPS(pixdata I,
	uniform sampler2D   texture0,
	uniform sampler2D   texture1,
	uniform sampler2D   texture2,
    uniform sampler2D   shadow_texture,
	uniform samplerCUBE textureCube,
	uniform float4      system_data)
{
	fragout O;

#ifdef SM1_1
	s2half4 tex0 = tex2D(texture0, I.texcoord0.xy);
	O.col = float4(tex0.xyz, 1.0);
#else
	float time = system_data.x;

	s2half4 tex0 = tex2D(texture0, I.texcoord0.xy);
	s2half4 shadow = tex2Dproj(shadow_texture, I.screenCoord);

  //take the wobbly effect from the fx6 shader (it's called "fx6" in surface.txt, but the shader is called "ambDiffFx5.shader")
	float4 sum_color = float4(0.0, 0.0, 0.0, 0.0);
	float I = 0, sum_num = 6;
	for(I = 0; I < sum_num; I++)
	{
	  //calc horizontal offset
		float2 offsetUV = I.texcoord0.xy / 5.0;
	  //make it a little bit slower than in fx6
		offsetUV.y += frac(0.55 + 0.3375 * I * time / sum_num + 0.15 + I / sum_num);
		s2half4 wave_offset = tex2D(texture2, offsetUV);
		float h_offs = (I / sum_num) + (0.1 + 0.03 * I / sum_num) * (wave_offset.x - 0.5);
		
	  //calc vertical offset
		offsetUV = I.texcoord0.xy / 5.0;
		wave_offset = tex2D(texture2, offsetUV);
		float v_offs = (0.3 * I / sum_num) * wave_offset.z * (wave_offset.y - 0.5);

	  //calc lookup
		float2 newUV = I.texcoord0.xy / 5.0;
	  //increase range of wobblyness compared to fx6 through multiplying by 2
		newUV += 2.0 * float2(h_offs, v_offs);

	  //fx base color
		s2half4 base_color = tex2D(texture1, newUV);
		base_color = pow(base_color, 1.0 + 2.0 * wave_offset.x + 2.0 * wave_offset.y);
		
	  //fx sum color
		sum_color += base_color;
	}

	sum_color /= sum_num;
	
  //end of fx6's wobbly effect calculation
	  
  //HSL color room's Lightness and Saturation from RGB color room
	  //sum_color
		float lightness_gamma_corrected_sum = (0.2126 * sum_color.x) + (0.7152 * sum_color.y) + (0.0722 * sum_color.z);
	  //tex0
		float saturation_tex0 = sqrt(dot(tex0.xyz, tex0.xyz) - dot(tex0.xyz, tex0.yzx));
		float lightness_gamma_corrected_tex0 = 0.2126 * tex0.x + 0.7152 * tex0.y + 0.0722 * tex0.z;
		
  //compose wobbly+starry. saturation is necessary so that the stars don't get overlayed with the wobbly.
	float3 final_col = float3(0.0, 0.0, 0.0);
	float3 final_glow = float3(0.0, 0.0, 0.0);
	float glow_intensity = 0.0;
  //star
	if ((1.0 - saturation_tex0) * lightness_gamma_corrected_tex0 > 0.27) {
		final_col = tex0.xyz;
		final_glow = tex0.xyz;
	  //high_nebula
		if (lightness_gamma_corrected_sum > 0.05f) {
		//aimed effect: stars inside nebulas shall glow bright
		
			glow_intensity = lightness_gamma_corrected_tex0;
		}
	  //low_nebula
		else {
		//aimed effect: visual difference between glowing star inside nebula and normal background star outside nebula
		
		  //the lower the dimm value, the more the star gets dimmed
			float dimm_min = 0.5f;
			float dimm_max = 1.0f;
		  //the less saturation and the more brightness, the more the star gets dimmed aka the lower the dimm value
			float dimm = lerp(dimm_min, dimm_max, sqrt(saturation_tex0 * (1.0f - lightness_gamma_corrected_tex0)));
			float glow_min = lightness_gamma_corrected_tex0 * dimm;
			float glow_max = lightness_gamma_corrected_sum;
			final_col *= dimm;
			final_glow *= dimm;
		  //multiply by 20.0 because (0.0 < lightness_gamma_corrected_sum < 0.05) and (20.0 * 0.05 = 1)
			glow_intensity = lerp(glow_min, glow_max, 20.0 * lightness_gamma_corrected_sum);
		}
	}
  //no_star
	else {
	  //high_nebula
		if (lightness_gamma_corrected_sum > 0.05) {
		//aimed effect: nebula replaces everything that is not a star and glows a little bit
		
			final_col = sum_color.xyz;
			final_glow = sum_color.xyz;
			glow_intensity = 0.35;
		}
	  //low_nebula
		else {
		//aimed effect: smooth fade-off of nebula diffuse and glow into starry background
		
		  //multiply by 20.0 because (0.0 < lightness_gamma_corrected_sum < 0.05) and (20.0 * 0.05 = 1)
			float lerpval =  20.0 * lightness_gamma_corrected_sum;
			
		  //calc diffuse, glow and glow_intensity for starry and nebula
		  
			//copy code from star/low_nebula
			  float dimm_min = 0.5f;
			  float dimm_max = 1.0f;
			  float dimm = lerp(dimm_min, dimm_max, sqrt(saturation_tex0 * (1.0f - lightness_gamma_corrected_tex0)));
			  float glow_min = lightness_gamma_corrected_tex0 * dimm;
			  float glow_max = lightness_gamma_corrected_sum;
			  
			//diffuse
			  float3 diffuse_starry = tex0.xyz * dimm;
			  float3 diffuse_nebula = sum_color.xyz;
			  
			//glow
			  float3 glow_starry = tex0.xyz * dimm;
			  float3 glow_nebula = sum_color.xyz;
			  
			//intensity
			  float glow_intensity_starry = lerp(glow_min, glow_max, lerpval);
			  float glow_intensity_nebula = 0.35;
			  
		  //compose
			final_col = lerp(diffuse_starry, diffuse_nebula.xyz, lerpval);
			final_glow = lerp(glow_starry, glow_nebula.xyz, lerpval);
			glow_intensity = lerp(glow_intensity_starry, glow_intensity_nebula, lerpval);
		}
	}

  //apply intensity
	final_glow *= glow_intensity;

  //and ready to go
	O.col[0] = float4(final_col, tex0.w);
	O.col[1] = float4(final_glow, tex0.w);
#endif

	return O;
} 

 

It was totally worth it!

On 6/10/2022 at 2:03 AM, gogoblender said:

beautiful effect with the robes.. and the zoom you pulled off makes it magnetic approach, good drama lindor.

gonna show it to Schot, maybe there's also an idea here for default avatars for DarkMatters when new members register?

:thumbsup:

gogo

Forgot to answer last time, sry:D Uh I like the idea:agreed: Custom avatars for every Sacred/Sacred 2 character sounds amazing! Take what you want!! Do you want the original GIF or should I make a new one with the final version? A lot gets lost during the GIF transformation however.

Edited by Lindor
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...
Please Sign In or Sign Up