Glsl 在片段着色器中绘制球体法线贴图

Glsl 在片段着色器中绘制球体法线贴图,glsl,webgl,Glsl,Webgl,我尝试在片段着色器中使用GL_点绘制一个简单的球体,并使用法线贴图。目前,我只需在屏幕上画一个点,然后应用片段着色器将其“球化” 但是,我无法正确地为球体着色(或者至少我认为是这样)。似乎我在正确计算z,但当我将“法线”颜色应用于gl_FragColor时,它看起来不太正确(或者这是法线贴图所期望的吗?)。我假设gl_PointCoord和fragment coord之间存在一些不一致,但我不能完全理解 顶点着色器 precision mediump float; attribute vec3

我尝试在片段着色器中使用GL_点绘制一个简单的球体,并使用法线贴图。目前,我只需在屏幕上画一个点,然后应用片段着色器将其“球化”

但是,我无法正确地为球体着色(或者至少我认为是这样)。似乎我在正确计算z,但当我将“法线”颜色应用于
gl_FragColor
时,它看起来不太正确(或者这是法线贴图所期望的吗?)。我假设gl_PointCoord和fragment coord之间存在一些不一致,但我不能完全理解

顶点着色器

precision mediump float;

attribute vec3 position;

void main() {
  gl_PointSize = 500.0;
  gl_Position = vec4(position.xyz, 1.0);
}
片段着色器

precision mediump float;

void main() {

  float x = gl_PointCoord.x * 2.0 - 1.0;
  float y = gl_PointCoord.y * 2.0 - 1.0;

  float z = sqrt(1.0 - (pow(x, 2.0) + pow(y, 2.0)));

  vec3 position = vec3(x, y, z);

  float mag = dot(position.xy, position.xy);
  if(mag > 1.0) discard;

  vec3 normal = normalize(position);

  gl_FragColor = vec4(normal, 1.0);
}
实际产量:

预期产出:


首先,面向相机的法线
[0,0,-1]
应为rgb值:
[0.5,0.5,1.0]
。您必须重新调整大小,以将这些负值移动到
0
1
之间

其次,球体的法线不会线性变化,而是以正弦波的形式变化。所以你需要一些三角函数。对我来说,从垂直法线开始,然后旋转法线一个角度是有意义的,因为这个角度是线性变化的

通过对这个问题的研究,我得出了以下结论:


从这里使用一些旋转功能:

颜色通道被钳制在[0,1]范围内。(0,0,0)是黑色的,(1,1,1)是完全白色的

由于法向量是归一化的,因此其分量在[-1,1]范围内。 要获得预期结果,必须将法向量从范围[-1,1]映射到[0,1]:

vec3 normal_col = normalize(position) * 0.5 + 0.5;
gl_FragColor    = vec4(normal_col, 1.0);

如果使用
abs
值,则大小相同的正值和负值具有相同的颜色表示。颜色的强度随值的渐变而增加:

vec3 normal_col = abs(normalize(position));
gl_FragColor    = vec4(normal_col, 1.0);

我曾尝试过
0.5+0.5
,它似乎工作正常,但我不知道为什么会出现这种情况,我认为我只是毫无理由地在那里输入数字。谢谢你的解释!