Page 8 of 8

Re: [Patch] Textures

PostPosted: Mon Jan 15, 2018 6:34 am
by Ian
Well, 256 could be a valid scaling factor, but so high no one bothered to use it. It's impossible to say unless it's actually used anywhere.

Re: [Patch] Textures

PostPosted: Mon Jan 15, 2018 6:56 am
by HarryTuttle
Ian wrote:Well, 256 could be a valid scaling factor

Yeah, I forgot you store the values as floats. Since I operate on int in shader I had to resort to clamping to avoid div by 0...

Re: [Patch] Textures

PostPosted: Fri Oct 05, 2018 6:07 am
by Ian
Code: Select all
float LinearTexLocations(int wrapMode, float size, float u, out float u0, out float u1)
{
   float texelSize      = 1.0 / size;
   float halfTexelSize   = 0.5 / size;

   if(wrapMode==0) {                     // repeat
      u   = (u * size) - 0.5;
      u0   = (floor(u) + 0.5) / size;         // + 0.5 offset added to push us into the centre of a pixel, without we'll get rounding errors
      u0   = fract(u0);
      u1   = u0 + texelSize;
      u1   = fract(u1);

      return fract(u);                  // return weight
   }
   else if(wrapMode==1) {                  // repeat + clamp
      u   = fract(u);                     // must force into 0-1 to start
      u   = (u * size) - 0.5;
      u0   = (floor(u) + 0.5) / size;         // + 0.5 offset added to push us into the centre of a pixel, without we'll get rounding errors
      u1   = u0 + texelSize;

      if(u0 < 0.0)   u0 = 0.0;
      if(u1 > 1.0)   u1 = 1.0 - halfTexelSize;
      
      return fract(u);                  // return weight
   }
   else {                              // mirror + mirror clamp - both are the same since the edge pixels are repeated anyway

      float odd = floor(mod(u, 2.0));         // odd values are mirrored

      if(odd > 0.0) {
         u = 1.0 - fract(u);
      }
      else {
         u = fract(u);
      }

      u   = (u * size) - 0.5;
      u0   = (floor(u) + 0.5) / size;         // + 0.5 offset added to push us into the centre of a pixel, without we'll get rounding errors
      u1   = u0 + texelSize;

      if(u0 < 0.0)   u0 = 0.0;
      if(u1 > 1.0)   u1 = 1.0 - halfTexelSize;
      
      return fract(u);                  // return weight
   }
}

vec4 texBiLinear(sampler2D texSampler, int wrapMode, vec2 texCoord)
{
   float tx[2], ty[2];
   float a = LinearTexLocations(wrapMode,fWidth, texCoord.x,tx[0],tx[1]);
   float b = LinearTexLocations(wrapMode,fHeight,texCoord.y,ty[0],ty[1]);
   
   vec4 p0q0 = texture2D(texSampler, vec2(tx[0],ty[0]));
    vec4 p1q0 = texture2D(texSampler, vec2(tx[1],ty[0]));
    vec4 p0q1 = texture2D(texSampler, vec2(tx[0],ty[1]));
    vec4 p1q1 = texture2D(texSampler, vec2(tx[1],ty[1]));

   // Interpolation in X direction.
    vec4 pInterp_q0 = mix( p0q0, p1q0, a ); // Interpolates top row in X direction.
    vec4 pInterp_q1 = mix( p0q1, p1q1, a ); // Interpolates bottom row in X direction.

    return mix( pInterp_q0, pInterp_q1, b ); // Interpolate in Y direction.
}


One for Harry :) This emulates bilinear filtering in the shader .. also correctly handles the weird non smooth texture repeat, which is actually a combination in opengl of something like .. GL_CLAMP_TO_EDGE and GL_REPEAT. No equivalent function exists in opengl. Currently I fudged a solution by stretching the texture coordinates inside the polys to not sample the edge pixels, but this has its draw backs (ie doesn't work with mipmapping). This should improve the situation.

If we can add your code for pixel dilate for contour or alpha textures, and add in mipmapping, we'll have a very accurate emulation of what the model3 is doing.

Re: [Patch] Textures

PostPosted: Mon Oct 08, 2018 11:37 am
by Ian
Harry posted this some time ago ..

Image

With this description

Regarding my last post, pixel "dilate": I'm using my version of bilinear filtering resulting from 9 texel fetches appropriately blended

What is happening here, instead, is that the edge texels "bleed" toward the "outer", transparent, texture area copying their RGB values there, while leaving the alpha channel intact. Infact the texture edge is cut in respect of the original alpha value, while its color is replicated from the "inner" texels.

This fixes, with the appropriate contour threshold, all the ugly white/black borders (but even some colored ones) in contour textures.


I think he was 100% correct in what was happening. But a bilinear filter is just 4 texture samples. Seems unlikely they would have used 9 texture samples to achieve this ..

Anyway I tried modifying regular bilinear filtering to achieve this (ie with 4 samples ..) and this is the result

Image

I just fetch the 4 texture samples. Then for each one check the 2 adjacent pixels and if necessary copy their colour, leaving the alpha untouched.

Code: Select all
   vec4 p0q0 = texture2DLod(texSampler, vec2(tx[0],ty[0]), 0.0);
    vec4 p1q0 = texture2DLod(texSampler, vec2(tx[1],ty[0]), 0.0);
    vec4 p0q1 = texture2DLod(texSampler, vec2(tx[0],ty[1]), 0.0);
    vec4 p1q1 = texture2DLod(texSampler, vec2(tx[1],ty[1]), 0.0);

   if(alphaTest) {
      if(p0q0.a > p1q0.a)      { p1q0.rgb = p0q0.rgb; }
      if(p0q0.a > p0q1.a)      { p0q1.rgb = p0q0.rgb; }

      if(p1q0.a > p0q0.a)      { p0q0.rgb = p1q0.rgb; }
      if(p1q0.a > p1q1.a)      { p1q1.rgb = p1q0.rgb; }

      if(p0q1.a > p0q0.a)      { p0q0.rgb = p0q1.rgb; }
      if(p0q1.a > p1q1.a)      { p1q1.rgb = p0q1.rgb; }

      if(p1q1.a > p0q1.a)      { p0q1.rgb = p1q1.rgb; }
      if(p1q1.a > p1q0.a)      { p1q0.rgb = p1q1.rgb; }
   }


Probably a more efficient way of doing that? but it works anyway. That level of branching would kill gpus from yesteryear lol