【问题标题】:OpenGL - How could I color objects in pixelated fashion through shaders?OpenGL - 如何通过着色器以像素化方式为对象着色?
【发布时间】:2021-10-13 14:28:31
【问题描述】:

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

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

进入这个:

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

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

顶点着色器:

#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);
}

【问题讨论】:

  • " 但是我无法访问片段的本地位置来确定它所属的“假像素”“为什么不呢?这就是gl_FragCoord 的意义所在。不知道你对“局部位置”的意思是什么,但是如果你需要一些不与窗口空间像素对齐的像素光栅,你可以在顶点着色器中计算这个光栅中的位置,然后将它插值传递给片段着色器。跨度>
  • gl_FragCoord 给出了相对于窗口的位置。如果有意义的话,我想要一种方法来确定相对于对象本身的位置。
  • 正如我所说,您可以这样做。您只需要以数学方式指定您的像素栅格,然后您就可以实现它
  • 请包含一些代码以显示您如何生成非像素化图像。
  • 您必须向我们展示您的片段着色器代码。

标签: opengl glsl shader fragment-shader vertex-shader


【解决方案1】:

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

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

在下面使用pos 而不是oPos

请注意,这仅在 oPos 是视图空间中的位置时才有效,如果 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)。

【讨论】:

  • 谢谢,这很好用。我确实假设所有法线都指向屏幕。但是,我仍然必须考虑到某些对象不会与内部正方形正确对齐的事实,从而导致 problems like this 。我想解决方案是在级联位置之前计算某个值,以指示每个内部正方形相对于对象的位置。
  • @bieux 如果要将内部正方形与对象对齐,则需要引入纹理坐标。其中对象的左下角坐标为 (0, 0),右上角为 (1, 1)。 v
猜你喜欢
  • 1970-01-01
  • 2018-06-10
  • 2012-10-17
  • 2011-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-19
  • 2022-01-27
相关资源
最近更新 更多