OpenGL - 如何通过着色器以像素化方式为对象着色?

OpenGL - How could I color objects in pixelated fashion through shaders?

我正在尝试找出一种通过使用着色器以像素化方式照亮我的对象的方法。

为了说明,我的目标是把这个:

进入这个:

我已经尝试通过片段着色器寻找实现此目的的方法,但是,我无法访问片段的本地位置以确定它属于的“假像素”。我也有使用几何着色器为每个盒子创建顶点的想法,但我怀疑是否有更好的方法来做到这一点。有可能吗?

编辑:这些是当前用于第一张图片所示对象的着色器:

顶点着色器:

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTex;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

out vec3 oColor; //Output of a color
out vec2 oTex; //Output of a Texture
out vec3 oPos; //Output of Position in space for light calculation
out vec3 oNormal; //Output of Normal vector for light calculation. 

void main(){
    gl_Position = projection * view * model * vec4(aPos, 1.0);
    oColor = aColor;
    oTex = aTex;
    oPos = vec3(model * vec4(aPos, 1.0));
    oNormal = vec3(0, 0, -1); //Not being calculated at the moment.
}

片段着色器:

#version 330 core

in vec3 oColor;
in vec2 oTex;
in vec3 oPos;  
in vec3 oNormal;  

out vec4 FragColor;

uniform sampler2D tex;
uniform vec3 lightColor; //Color of the light on the scene, there's only one
uniform vec3 lightPos; //Position of the light on the scene

void main(){
   //Ambient Light Calculation
   float ambientStrength = 0.1;
   //vec3 ambient = ambientStrength * lightColor * vec3(texture(tex, oTex));
   vec3 ambient = ambientStrength * lightColor;

   //Diffuse Light Calculation
   float diffuseStrength = 1.0;
   vec3 norm = normalize(oNormal);
   vec3 lightDir = normalize(lightPos - oPos);

   float diff = max(dot(norm, lightDir), 0.0);
   //vec3 diffuse = diff * lightColor* vec3(texture(tex, oTex)) * diffuseStrength;
   vec3 diffuse = diff * lightColor;

   //Specular Light Calculation
   float specularStrength = 0.25;
   float shinnyness = 8;
   vec3 viewPos = vec3(0, 0, -10);

   vec3 viewDir = normalize(viewPos - oPos);
   vec3 reflectDir = reflect(-lightDir, norm);    

   float spec = pow(max(dot(viewDir, reflectDir), 0.0), shinnyness);
   vec3 specular = specularStrength * spec * lightColor;  

   //Result Light
   vec3 result = (ambient+diffuse+specular) * oColor;
   FragColor = vec4(result, 1.0f);
}

灯光取决于oPos。您需要“级联”该职位。例如:

vec3 pos = vec3(round(oPos.xy * 10.0) / 10.0, oPos.z);

在下面使用 pos 而不是 oPos

请注意,这仅在 oPos 是视图 space 中的一个位置时才有效,如果 oPos` 坐标系的 XY 平面平行于视图的 XY 平面。


或者,您可以根据 gl_FragCoord.

计算 a 位置

添加一个统一的屏幕分辨率变量:

uniform vec2 resolution;

根据resolutiongl_FragCoord计算pos

vec3 pos = vec3(round(20.0 * gl_FragCoord.xy/resolution.y) / 20.0, oPos.z);

如果要将内部方块与需要引入纹理坐标的对象对齐。其中对象的左下坐标为(0, 0),右上坐标为(1, 1)。