我想第一次在WebGL场景中实现阴影,据我所知,最直接的方法是使用阴影贴图,但我找不到解释这个概念的教程,这不是关于OpenGL,就是包含像three.js这样的库。如何在WebGL中实现阴影映射?
但是,我读过,我必须写两对着色器。第一对着色器用于构建阴影贴图,该贴图必须存储在帧缓冲区对象中。然后,我将不得不从帧缓冲区中取出存储的阴影贴图,并将其传递给第二对着色器,用于绘制场景中的对象。
阴影贴图必须包含信息,在光线照射到物体之前光源可以从光源传播的距离,并将该信息传递给用于绘制物体的着色器,这将有可能指定哪些部件通过来自光源的光点亮,哪些部件仅通过环境光照亮。
好这么多的理论,但我不知道该怎样得到这个工作的想法...
对于实验,我已经建立了一个非常简单的场景,呈现由单一的点光源照明两个领域源,它看起来像这样:
两个领域在[0.0, 0.0, 0.0]
和半径1.0
它们的中心创建的。
较大球体的矩阵由[-2.0, 0.0, -2.0]
翻译并由[2.0, 2.0, 2.0]
缩放。
较小球体的矩阵由[2.0, 0.0, 2.0]
翻译并且由[0.5, 0.5, 0.5]
缩放。
点光源的位置是[4.0, 0.0, 4.0]
。
因此,较小的球体现在只是在较大的球体和光源之间,因此在较大的球体表面上应该存在一个不直接点亮的区域。
两个着色器我用这个场景是这样的:
顶点着色器
attribute vec4 aPosition;
attribute vec3 aNormal;
uniform mat4 uProjectionMatrix;
uniform mat4 uModelViewMatrix;
uniform mat3 uNormalMatrix;
varying vec4 vPosition;
varying vec3 vTransformedNormal;
void main () {
vTransformedNormal = uNormalMatrix * aNormal;
vPosition = uModelViewMatrix * aPosition;
gl_Position = uProjectionMatrix * vPosition;
}
片段着色器
precision highp float;
uniform vec3 uLightPosition;
varying vec4 vPosition;
varying vec3 vTransformedNormal;
void main () {
vec3 lightDirection = normalize(uLightPosition - vPosition.xyz);
float diffuseLightWeighting = max(
dot(normalize(vTransformedNormal), lightDirection), 0.0);
vec3 lightWeighting = vec3(0.1, 0.1, 0.1) +
vec3(0.8, 0.8, 0.8) * diffuseLightWeighting;
gl_FragColor = vec4(vec3(1.0, 1.0, 1.0) * lightWeighting, 1.0);
}
所以,第一件事我会现在必须做的是编写另一对着色器,并且因为它们不习惯真正的博士在某种程度上,我可以忽略法线的属性以及法线矩阵的均匀性,也不需要投影矩阵,对吗?
第二个顶点着色器可以再看看这样的:
attribute vec4 aPosition;
uniform mat4 uModelViewMatrix;
varying vec4 vPosition;
void main () {
vPosition = uModelViewMatrix * aPosition;
gl_Position = vPosition;
}
有关片段着色器
可是什么?而且,无论如何,我如何才能找出点光源发出的光线照射到物体的哪个位置?我的意思是,一般需要从全部相关对象一次传递顶点位置数据,不是吗? (虽然在这种特殊情况下,只需要通过较小球体的顶点位置......)
现在,我的问题是,我怎么从这里继续?必须写入片段着色器,如何保存阴影贴图,以及如何使用它来计算更大球体上较小球体的阴影?
我担心我可能需求太多,但如果有人能够至少让我指向正确的方向,那将是非常好的。
你好Wacław并非常感谢您的回答!那么,如果我找到了你的话,我首先要做的第一步就是创建一个'lightMatrix',它应该是一个mat4。因此,在第一遍的顶点着色器中,它看起来像'vPosition = lightMatrix * modelViewMatrix * aPosition',或者我也必须考虑projectionMatrix,比如'vPosition = uProjectionMatrix * lightMatrix * modelViewMatrix * aPosition'?为了获得第二遍vec3,我必须通过添加'1'作为第四个值来使用像glMatrix'vec4.transformMat4'这样的东西,对吧? – SickBoy
我也很难找到关于深度纹理的东西:MSDN根本没有描述这个扩展,而MDN只有一个死链接。基本语法应该是'depthTexture = gl.getExtension('WEBGL_depth_texture')',对吧?你有什么链接可以看到哪些浏览器支持这个功能? _caniuse.com_对WebGL没有用处,上面提到的网络也没有。我记得我已经阅读过有关将值存储为常规纹理的RGBA值的内容,因此可以用作后备?看起来,learnwebgl.com已经离线了...... – SickBoy
......这非常令人伤心,因为如果我没有记错的话,还有关于如何使用frameBuffer对象来制作可用于第二遍。我从来没有使用过这种技术,因此我对它的工作原理只有一些模糊的想法 - 现在我找不到解释这一点的文章或教程。但是,对我来说,这是一个很大的问题:如果你想学习纯WebGL,很难找到任何文章,文档和教程!这就像试图学习JavaScript一样,你在网上找到的所有东西都只是关于jQuery或Java。 :-( – SickBoy