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

标签 glsl webgl

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

但是,我在正确为球体着色时遇到了困难(或者至少我认为是)。看来我正确地计算了 z,但是当我将“正常”颜色应用于 gl_FragColor 时,它看起来不太正确(或者这是人们对法线贴图的期望?) 。我假设 gl_PointCoord 和片段坐标之间存在一些不一致,但我不太明白。

顶点着色器

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

实际输出:

enter image description here

预期输出:

enter image description here

最佳答案

颜色 channel 被限制在 [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);

关于glsl - 在片段着色器中绘制球体法线贴图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53271461/

相关文章:

javascript - 为什么 gl.drawElements 需要重新绑定(bind),而 gl.drawArrays 不需要?

javascript - 读取 WebGLTexture 中的像素(将 WebGL 渲染到纹理)

c++ - 发送 3 字节数据到 OpenGL GLSL

opengl - 单遍线框问题

javascript - 提供一个对话框以在 Web 应用程序上使用浏览器固有的全屏

html - 负 z-index 会影响性能或兼容性吗?

html - 我应该学习哪种浏览器图形 API?

opengl - 模型 View 投影中的第四行是查看位置吗?

c++ - 帧缓冲区深度伪影

glsl - Vulkan GLSL 的统一纹素缓冲区