为什么基本的镜面阴影是流动的,而不是锯齿状的?

时间:2016-02-23 09:28:47

标签: c++ opengl glsl shading

简单的问题,我只是让我的第一个镜面着色器工作,并查看数学,我不能帮助认为每个边缘之间的角度应该导致“镜面反射”尖峰/变成锯齿状。但它完全是流体/球形。

这个想法是计算偏离顶点法线的角度,但是只有这么多,并且“镜面阴影”仍然完美无缺。

我无法看到gpu如何仅根据顶点法线知道片段的角度。

enter image description here

编辑:     vert shader

#version 400 core

layout ( location = 0 ) in vec3 vertex_position;
layout ( location = 2 ) in vec2 tex_cord;
layout ( location = 3 ) in vec3 vertex_normal;

uniform mat4 transform; //identity matrix
uniform mat3 lmodelmat; //inverse rotation

out vec2 UV;
out vec3 normal;

void main()
{
  UV=tex_cord;
  normal=normalize(vertex_normal*lmodelmat);  //normalize to keep brightness

  gl_Position=transform*vec4(vertex_position,1.0);
}

和frag

#version 400 core

in vec2 UV;
in vec3 normal;

uniform sampler2D mysampler;
uniform vec3 lightpos; //lights direction

out vec4 frag_colour;

in vec3 vert2cam; //specular test

void main()
{
  //skip invis frags
  vec4 alphatest=texture(mysampler,UV);
  if(alphatest.a<0.00001)discard; 

  //diffuse'ing fragment
  float diffuse=max(0.1,dot(normal,lightpos));

  //specular'izing fragment
  vec3 lpnorm=normalize(lightpos);  //vector from fragment to light
  vec3 reflection=normalize(reflect(-lpnorm,normal)); //reflection vector
  float specularity=max(0,dot(lpnorm,reflection));
  specularity=pow(specularity,50);

  frag_colour=alphatest*diffuse+specularity;
}

//修改

我找到了这个btw(一年后)的答案:Vertice法线(vn)是连接到它的每个面/三角形的组合值。也就是说,连接到多个面的1个顶点在标准化时将具有组合的面法线。该值vn被计算为相邻面法线的平均值。当计算该值以指示亮度时,GPU将提供“阴影”,这是每个附近边的标准化交叉积。

我在重新计算项目的面部法线时想到了这一点:

重新计算顶点法线的伪代码:

for (for each face/triangle, find face-normal and add to adjacent vn's) 
vec3 face_normal=cross(face[1]-face[0],face[2]-face[0]);
vn[0]+=face_normal; //notice +=
vn[1]+=face_normal;
vn[2]+=face_normal;

//then just normalize them to get the weighted average
for(auto&x:vn)x=normalize(x);

对于渲染器,这将等同于平均曲线,而不是锯齿状边缘(平面阴影)

1 个答案:

答案 0 :(得分:2)

没有代码.etc。很难准确回答你的问题,但假设一个简单的矢量着色器 - &gt;片段着色器管道。将为每个顶点运行矢量着色器。它将设置通常设置的标记为“变化”的参数。 (例如纹理坐标)。

每3个顶点将被分组以形成多边形,并且片段着色器运行以确定多边形内每个点的颜色。 &#39;变化&#39;由顶点着色器设置的参数将根据片段与多边形的3个边缘的距离进行插值(参见:重心插值)。

因此例如:

gl_FragColor = texture2D(myUniformSampler, vec2(myTextureCoord.s,myTextureCoord.t));

将为每个像素正确采样纹理。假设您正在使用每片段光照,则可能会根据您在顶点着色器中设置的值为每个片段着色器插值。如果为每条边设置相同的法线,则会产生不同的效果。

编辑(根据您添加的代码):

out vec2 UV;
out vec3 normal;
out vec3 color;

在顶点着色器中为每个顶点设置。每三个顶点定义一个多边形。然后对多边形内的每个点(例如像素)运行片段着色器以确定颜色.etc。每一点。

这些参数的值:

in vec3 color; /// <<-- You don't seem to be actually using this
in vec2 UV;
in vec3 normal;
片段着色器中的

是根据被绘制的多边形上的点的距离进行插值的。来自每个顶点(参见:重心插值)。因此,法线在顶点着色器定义的顶点之间变化。

如果对于由三个顶点定义的给定多边形,您将法线设置为朝向相同方向,则会产生不同的效果。