想象一个场景,您有一个非常大的 THREE.PlaneGeometry 模拟地板,并且您有一个相机添加到场景中的随机位置。
如果我手动调整雾的近距和远距值,我可以以某种方式隐藏飞机的外部,给人一种无限的印象。到目前为止,一切都很好。
问题是,如果我让相机在场景中飞到飞机内的随机位置会怎样?如果随机点距离飞机外部足够近,则雾不会掩盖飞机的末端,因为雾始终基于相机位置。
所以我的问题是,只有当你足够接近飞机的极限时,我们如何才能实现雾效果?
我正在编写一个自定义 ShaderMaterial,并决定包含灯光和雾。到目前为止一切顺利,我将着色器与 Three.js 集成,构建了雾灯、环境光和点光源(它满足了我的目的)。
然而,我得到的阴影是平滑的,而不是平坦的。在你们决定建议将shading: THREE.FlatShading标志添加到 ShaderMaterial 之前,请记住这是一个自定义着色器,因此不会真正执行任何操作。
由于 FlatShading 是通过计算三角形质心并根据该向量填充所有颜色来完成的,因此我认为使用三角形顶点的法线就可以解决问题..显然它不会...这是正确拥有 FlatShading 光的一种方法吗三角形内的所有像素都有 1 种单一颜色?如果是这样,我错过了什么?
这是我在 CoffeeScript 中的着色器
一些着色器类
constructor: ->
@defines = {}
@uniforms = THREE.UniformsUtils.merge [
THREE.UniformsLib['fog']
THREE.UniformsLib['lights']
{
color: { type: 'c', value: new THREE.Color(0xffffff) }
}
]
@vertex = [
'uniform vec3 ambientLightColor;'
'#if MAX_POINT_LIGHTS > 0'
' uniform vec3 pointLightColor[MAX_POINT_LIGHTS];'
' uniform vec3 pointLightPosition[MAX_POINT_LIGHTS];'
' uniform float pointLightDistance[MAX_POINT_LIGHTS];'
'#endif'
'uniform vec3 color;'
'varying vec4 v_color;'
'void main() {'
# lights
' vec3 norm …Run Code Online (Sandbox Code Playgroud) 我创建了一个纹理和一个渲染缓冲区来将现有 3D 场景渲染为纹理,并使用该纹理作为另一个 webgl 程序的输入。
下面是处理将场景渲染到纹理的类的伪代码。
根据需要更新纹理宽度和高度的最佳方法是什么(例如,如果浏览器调整大小)?我是否需要每次都创建一个新的纹理/渲染缓冲区?
我想知道是否可以使用比目前更少的代码来完成此操作?
class Renderer {
constructor() {
// creates the texture and framebuffer for the first time
this.updateRTT(128, 128);
}
updateRTT(width, height) {
const gl = getContext();
this.rttwidth = width;
this.rttheight = height;
console.log('update RTT', this.rttwidth, this.rttheight);
this.frameBuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer);
this.texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.rttwidth, this.rttheight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
this.renderBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, …Run Code Online (Sandbox Code Playgroud) 使用WebGL 2,我们现在可以使用统一缓冲区对象.
它们看起来是个好主意,不必将常见的制服附加到每个程序(如每个被渲染对象共有的投影和视图矩阵).
我创建了一个帮助器类,每次我想绑定一个统一的缓冲区对象时都会调用它.
class UniformBuffer {
constructor(gl, data, boundLocation = 0) {
this.boundLocation = boundLocation;
this.data = new Float32Array(data);
this.buffer = gl.createBuffer();
gl.bindBuffer(gl.UNIFORM_BUFFER, this.buffer);
gl.bufferData(gl.UNIFORM_BUFFER, this.data, gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.UNIFORM_BUFFER, null);
gl.bindBufferBase(gl.UNIFORM_BUFFER, this.boundLocation, this.buffer);
}
update(gl, data, offset = 0) {
this.data.set(data, offset);
gl.bindBuffer(gl.UNIFORM_BUFFER, this.buffer);
gl.bufferSubData(gl.UNIFORM_BUFFER, 0, this.data, 0, null);
gl.bindBuffer(gl.UNIFORM_BUFFER, null);
gl.bindBufferBase(gl.UNIFORM_BUFFER, this.boundLocation, this.buffer);
}
};
Run Code Online (Sandbox Code Playgroud)
想要创建像这样的统一缓冲区的想法
const perScene = new UniformBuffer(gl, [
...vec4.create(),
...vec4.create(),
], 0); // and bind it to bind location 0?
const perObject = new UniformBuffer(gl, …Run Code Online (Sandbox Code Playgroud)