How to retrieve screen resolution inside a shader?

All topics about ZGameEditor goes here.

Moderator: Moderators

Post Reply
User avatar
Ats
Posts: 764
Joined: Fri Sep 28, 2012 10:05 am
Contact:

How to retrieve screen resolution inside a shader?

Post by Ats »

Hello, I'm back at figuring out shaders... :lol:
I'm trying to retrieve the screen resolution inside a shader, and right now, I found no other way but to create in a ZExpression

ScreenSize : Array <mat4>

Then store the information inside it:
ScreenSize[0][0,0] = App.ScreenWidth;
ScreenSize[0][0,1] = App.ScreenHeight;

Then having a shaderVariable in my shader:
screenSize (ValueArrayRef:ScreenSize, ArrayKind:Mat4)

And use it in the shader:
float ditherScale = min(screenSize[0][0], screenSize[0][1]) / 640.0;

While it works, this seems overly complicated. Is there some other way to do that?
And as I'm writing it, I think it would be best to calculate the ditherScale during initialization, then pass that float to the shader.
Last edited by Ats on Thu Apr 18, 2024 3:55 pm, edited 1 time in total.
User avatar
Kjell
Posts: 1915
Joined: Sat Feb 23, 2008 11:15 pm

Re: How to retrieve screen resolution inside a shader?

Post by Kjell »

Hi Ats,
Ats wrote: Thu Apr 18, 2024 2:56 pmI'm trying to retrieve the screen resolution inside a shader
What do you need the screen resolution for in your shader? If it's just to calculate "ditherScale", then simply calculate that value in a ZExpression instead and pass the result as a ShaderVariable.

But it's easier to give you a proper suggestion when i know exactly what you're trying to do :wink:

K
User avatar
Ats
Posts: 764
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: How to retrieve screen resolution inside a shader?

Post by Ats »

That's the conclusion I went through while writing my question, in the end :lol:
I'm writing a diffuse + dithering shader (I think I do), with a pixel density that stays the same regardless of the game resolution:

Code: Select all

#ifdef GL_ES
  precision mediump float;
#endif

varying vec3 N;
varying vec3 v;
varying vec4 v_Color;

uniform vec4 globalColor; // = Material.Color
uniform mat4 lightPosition;
uniform mat4 lightColorAmbient;
uniform mat4 fogColor;

// Dithering pattern
const mat3 ditherMatrix = mat3(
    0.0, 0.5, 0.125,
    0.75, 0.25, 0.625,
    0.1875, 0.6875, 0.0625
);

// Screen size
uniform mat4 screenSize;

void main (void)
{
  // Light position
  vec3 LPosition = vec3(lightPosition[0][0], lightPosition[0][1], lightPosition[0][2]);
  vec3 L = normalize(LPosition - v);

  // calculate Diffuse Term
  vec4 LAmbient = vec4(lightColorAmbient[0][0], lightColorAmbient[0][1], lightColorAmbient[0][2], 1.0);
  vec4 LDiffuse = globalColor * LAmbient;

  // clamp pour éviter les couleurs brulées sur android avec la distance de la lumière
  vec4 Idiff = 3.0 * LDiffuse * max(dot(N,L), 0.0);

  // Réglages des contrastes (fait planter le jeu sur android!? Parce que j'avais mis 1 au lieu de 1.0)
  Idiff = (0.7 * (Idiff + 1.0) - 1.0 + 0.4) * 0.5 + 0.5;

  // Calculate dithering scale based on screen resolution
  float ditherScale = min(screenSize[0][0], screenSize[0][1]) / 640.0;

  // Dithering for surface shadow
  float ditherValue = ditherMatrix[int(gl_FragCoord.x / ditherScale) % 2][int(gl_FragCoord.y / ditherScale) % 3];
  float surfaceShadowIntensity = clamp(Idiff.r, 0.0, 1.0);
  float ditheredIntensity = mix(surfaceShadowIntensity, surfaceShadowIntensity + 0.05, ditherValue);
  vec4 ditheredColor = vec4(ditheredIntensity);

  // Fog
  vec4 fog = vec4(fogColor[0][0], fogColor[0][1], fogColor[0][2], 1.0);

  // Final color
  vec4 color = v_Color * ditheredColor;

  gl_FragColor = mix(color, fog, clamp(-v.z / 500.0, 0.0, 1.0));
}
dither.png
dither.png (14.9 KiB) Viewed 1462 times
Or maybe the dithering should be made on the final image, post process, I really don't know :oops:
User avatar
Kjell
Posts: 1915
Joined: Sat Feb 23, 2008 11:15 pm

Re: How to retrieve screen resolution inside a shader?

Post by Kjell »

Hi Ats,
Ats wrote: Thu Apr 18, 2024 3:48 pmI'm writing a diffuse + dithering shader (I think I do), with a pixel density that stays the same regardless of the game resolution
You could use gl_FragCoord for that. Here's a super-basic example .. "dithering" happens at pixel size of 4x4 pixels regardless of the viewport size ( change the pixel_size constant to adjust the desired pixel density ).

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" ScreenMode="0" FileVersion="2">
  <OnLoaded>
    <SpawnModel Model="Demo"/>
  </OnLoaded>
  <Content>
    <Model Name="Demo" RotationVelocity="0.2 0.3 0">
      <OnRender>
        <UseMaterial Material="DemoMaterial"/>
        <RenderMesh Mesh="DemoMesh"/>
      </OnRender>
    </Model>
    <Mesh Name="DemoMesh">
      <Producers>
        <MeshBox/>
      </Producers>
    </Mesh>
    <Shader Name="DemoShader">
      <VertexShaderSource>
<![CDATA[//

void main()
{
  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}]]>
      </VertexShaderSource>
      <FragmentShaderSource>
<![CDATA[//

const mat3 dither = mat3(0.0, 0.5, 0.125, 0.75, 0.25, 0.625, 0.1875, 0.6875, 0.0625);
const float pixel_size = 4.0;

//

void main()
{
  int x = int(mod(gl_FragCoord.x / pixel_size, 3.0));
  int y = int(mod(gl_FragCoord.y / pixel_size, 3.0));

  float s = dither[y][x];

  gl_FragColor = vec4(s, s, s, 1.0);
}]]>
      </FragmentShaderSource>
    </Shader>
    <Material Name="DemoMaterial" Shading="1" Light="0" Shader="DemoShader"/>
  </Content>
</ZApplication>
However, this might not always be the ideal approach .. and this doesn't have much to do with dithering either. Dithering is used to create the illusion of a greater color-depth than you're actually using. This is more like a "brightness pattern overlay", which you could do with a simple blended texture on a fullscreen quad as well.

K
User avatar
Ats
Posts: 764
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: How to retrieve screen resolution inside a shader?

Post by Ats »

Thanks. I'll see what I can do with that :wink:
I also managed to find the topic that was already talking about dithering with your examples:
https://www.emix8.org/forum/viewtopic.p ... 330&p=8649

(The search feature of phpbb isn't great...)
Post Reply