Glsl WebGL:在没有THREE.JS帮助的情况下添加镜面反射光

Glsl WebGL:在没有THREE.JS帮助的情况下添加镜面反射光,glsl,webgl,shader,fragment-shader,vertex-shader,Glsl,Webgl,Shader,Fragment Shader,Vertex Shader,我正在做一些webgl编程的第一步。创建了一个简单的设置如下。设法添加了一些我自己的东西,尽管在添加灯光时遇到了困难,特别是镜面反射灯光。 正如我所设想的,其中大部分将在我的片段着色器中实现,可能还会在顶点着色器和灯光模块中添加一些内容。这就是我在下面提供的代码 顶点着色器: attribute vec3 position; attribute vec3 normal; attribute vec2 uv; uniform mat4 model; uniform mat4 view; unifo

我正在做一些webgl编程的第一步。创建了一个简单的设置如下。设法添加了一些我自己的东西,尽管在添加灯光时遇到了困难,特别是镜面反射灯光。 正如我所设想的,其中大部分将在我的片段着色器中实现,可能还会在顶点着色器和灯光模块中添加一些内容。这就是我在下面提供的代码

顶点着色器:

attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
varying vec3 vNormal;
varying vec2 vUv;

void main() {
    vUv = uv;
    vNormal = (model * vec4(normal, 0.)).xyz;
    gl_Position = projection * view * model * vec4(position, 1.);
}
片段着色器:

#ifdef GL_ES
precision highp float;
#endif

uniform vec3 lightDirection;
uniform float ambientLight;
uniform sampler2D diffuse;
varying vec3 vNormal;
varying vec2 vUv;

void main() {
    float lightness = -clamp(dot(normalize(vNormal), normalize(lightDirection)), -1., 0.);
    lightness = ambientLight + (1. - ambientLight) * lightness;
    gl_FragColor = vec4(texture2D(diffuse, vUv).rgb * lightness, 1.);
}
Light.js模块:

function Light () {
  this.lightDirection = new Vector3(-1, -1, -1)
  this.ambientLight = 0.3
}

Light.prototype.use = function (shaderProgram) {
  var dir = this.lightDirection
  var gl = shaderProgram.gl
  gl.uniform3f(shaderProgram.lightDirection, dir.x, dir.y, dir.z)
  gl.uniform1f(shaderProgram.ambientLight, this.ambientLight)
}

我非常感谢你在这里的建议。提前谢谢

最常见和最简单的灯光模型是or模型

以下着色器代码基于原始代码并实现模型。与代码相比,灯光计算是在视图空间中完成的,因为镜面反射高光取决于视图位置,即视图空间中的(0,0,0)。因此,必须将灯光方向转换为视图空间

顶点着色器:

attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
varying vec3 vNormal;
varying vec2 vUv;

void main() {
    vUv = uv;
    vNormal = (model * vec4(normal, 0.)).xyz;
    gl_Position = projection * view * model * vec4(position, 1.);
}
属性向量3位置;
属性向量3正常;
属性向量2 uv;
统一mat4模型;
统一mat4视图;
均匀mat4投影;
方向一致;
可变vec3 VPO;
可变vec3 vNormal;
可变vec2 vUv;
可变vec3光方向视图;
void main()
{
lightDirectionView=(视图*vec4(lightDirection,0.)).xyz;
mat4模型视图=视图*模型;
vec4 viewPos=模型视图*vec4(位置,1.0)
vPos=viewPos.xyz;
vUv=紫外线;
vNormal=(modelView*vec4(normal,0.)).xyz;
gl_位置=投影*视图位置;
}
Fragemnt着色器:

#ifdef GL_ES
precision highp float;
#endif

uniform vec3 lightDirection;
uniform float ambientLight;
uniform sampler2D diffuse;
varying vec3 vNormal;
varying vec2 vUv;

void main() {
    float lightness = -clamp(dot(normalize(vNormal), normalize(lightDirection)), -1., 0.);
    lightness = ambientLight + (1. - ambientLight) * lightness;
    gl_FragColor = vec4(texture2D(diffuse, vUv).rgb * lightness, 1.);
}
\ifdef glu
高精度浮点;
#恩迪夫
均匀的浮光度;
均匀浮动环境光;
均匀二维漫反射;
可变vec3 VPO;
可变vec3 vNormal;
可变vec2 vUv;
可变vec3光方向视图;
void main()
{
vec3颜色=纹理2D(漫反射,vUv).rgb;
vec3 N=正常化(vNormal);
vec3 L=标准化(-lightDirectionView);
vec3 V=正常化(-VPO);
vec3 H=标准化(V+L);
float NdotL=点(N,L);
float NdotH=点(N,H);
浮动kDiffuse=max(0.0,NdotL);
//浮子K特殊=(光泽度+2.0)*功率(最大(0.0,NdotH),光泽度)/(2.0*3.14159265);
浮子K特殊=功率(最大值(0.0,第N个),光泽度);
vec3 light\u col=颜色*(kDiffuse+k特殊);
gl_FragColor=vec4(灯光颜色,1.0);
}
均匀光亮度的值必须在[1100]范围内为正值


另请参见。

您可能会喜欢@KseniaStarodubtseva,不客气。我很高兴能帮助你。Blinn-Phong没有被应用于
k特殊
的辐射标准化术语,而且
N
L
术语被翻转,通常
N
是正常的,
L
是光的方向。在片段着色器中对光的方向进行视图空间变换也是非常不必要的,因为从零向量(
V
term)中减去光的方向,而不仅仅是求反。@LJᛃ
N
L
是一个打字错误。@LJᛃ <代码>规范化(vec3(0.0)-VPO)旨在证明
V
是两个点之间的向量,其中viewspace中的视图位置为(0,0,0)。但不管怎样,谢谢。嗯,我明白了,对不起,我不是故意要破坏你的回答。我通常在世界空间中这样做,也就是说我觉得称之为“视图位置”是不明确的,因为对我来说,“视图位置”指的是视图空间中的顶点位置,而不是相机位置。