06-mini版WebGLState

源码:github.com/buglas/thre...

在后面的章节里我们会按照WebGLRenderer的initGLContext() 方法里的初始化顺序,简化其中的关键模块,我们会忽略一些与绘制纯色三角形无关的模块。

src\renderers\WebGLRenderer.js

ini 复制代码
function initGLContext() {
    extensions = new WebGLExtensions( _gl );
    extensions.init();
    utils = new WebGLUtils( _gl, extensions );
    capabilities = new WebGLCapabilities( _gl, extensions, parameters, utils );
    state = new WebGLState( _gl, extensions );
    if ( capabilities.reversedDepthBuffer && reversedDepthBuffer ) {
        state.buffers.depth.setReversed( true );
    }
    info = new WebGLInfo( _gl );
    properties = new WebGLProperties();
    textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
    environments = new WebGLEnvironments( _this );
    attributes = new WebGLAttributes( _gl );
    bindingStates = new WebGLBindingStates( _gl, attributes );
    geometries = new WebGLGeometries( _gl, attributes, info, bindingStates );
    objects = new WebGLObjects( _gl, geometries, attributes, bindingStates, info );
    morphtargets = new WebGLMorphtargets( _gl, capabilities, textures );
    clipping = new WebGLClipping( properties );
    programCache = new WebGLPrograms( _this, environments, extensions, capabilities, bindingStates, clipping );
    materials = new WebGLMaterials( _this, properties );
    renderLists = new WebGLRenderLists();
    renderStates = new WebGLRenderStates( extensions );
    background = new WebGLBackground( _this, environments, state, objects, _alpha, premultipliedAlpha );
    shadowMap = new WebGLShadowMap( _this, objects, capabilities );
    uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state );
    bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info );
    indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info );

接下来我们先说WebGLState,我会参考它新建一个src\renderers\webgl\WebGLStateMini.js文件。

src\renderers\WebGLRendererMini.js

javascript 复制代码
import { Vector4 } from '../../math/Vector4.js';
​
/**
 * GL 固定功能状态的最小封装。
 * Mini 版仅包含 clearColor、useProgram、viewport,不含深度/混合/裁剪等。
 */
function WebGLStateMini( gl ) {
    // 颜色缓冲区,如果当前颜色与传入颜色相同,则不进行操作
    function ColorBuffer() {
        const color = new Vector4();
        const currentColorClear = new Vector4( 0, 0, 0, 0 );
        return {
            setClear: function ( r, g, b, a ) {
                color.set( r, g, b, a );
                if ( currentColorClear.equals( color ) === false ) {
                    gl.clearColor( r, g, b, a );
                    currentColorClear.copy( color );
                }
            },
        };
    }
    // 颜色缓冲区实例
    const colorBuffer = new ColorBuffer();
    // 当前程序
    let currentProgram = null;
    // 设置颜色缓冲区清除颜色
    colorBuffer.setClear( 0, 0, 0, 1 );
    // 当前视口
    const currentViewport = new Vector4()
​
    // 使用着色器程序,如果当前程序与传入程序相同,则不进行操作
    function useProgram( program ) {
        if ( currentProgram !== program ) {
            gl.useProgram( program );
            currentProgram = program;
            return true;
        }
        return false;
    }
    // 设置视口,如果当前视口与传入视口相同,则不进行操作
    function viewport( viewport ) {
        if ( currentViewport.equals( viewport ) === false ) {
            gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
            currentViewport.copy( viewport );
        }
    }
    return {
        buffers: {
            color: colorBuffer,
        },
        useProgram: useProgram,
        viewport: viewport,
    };
}
​
export { WebGLStateMini };

1-WebGLState 的定位与职责

WebGLState 是 WebGL 的「全局状态」管理器,它可以设置背景色、视口、useProgram 等。

WebGL 有很多「全局状态」:当前 shader、视口、清除颜色、深度测试、混合模式等。

Three.js 不直接到处调用 gl.xxx,而是通过 State 层 统一管理,主要目的是:

  1. 封装 WebGL 原生 API
  2. 避免重复设置相同状态(减少 CPU → GPU 调用)

Mini 版只保留三条最基础的状态:

功能 GL API 用途
清屏颜色 gl.clearColor 背景/清屏
着色器程序 gl.useProgram 切换 shader
视口 gl.viewport 画布绘制区域

2-WebGLStateMini 代码详解

1. 工厂函数

javascript 复制代码
function WebGLStateMini( gl ) {

接收 WebGL2 上下文 gl,闭包保存当前状态,返回对外 API。

2. ColorBuffer --- 清屏颜色缓存

scss 复制代码
function ColorBuffer() {
    const color = new Vector4();
    const currentColorClear = new Vector4( 0, 0, 0, 0 );
    return {
        setClear: function ( r, g, b, a ) {
            color.set( r, g, b, a );
            if ( currentColorClear.equals( color ) === false ) {
                gl.clearColor( r, g, b, a );
                currentColorClear.copy( color );
            }
        },
    };
}
  • currentColorClear 记录上次传给 GL 的清除色
  • 新颜色与上次相同 → 跳过 gl.clearColor
  • 初始化时设为 (0, 0, 0, 1) 黑色不透明

3. useProgram --- 着色器程序缓存

ini 复制代码
function useProgram( program ) {
    if ( currentProgram !== program ) {
        gl.useProgram( program );
        currentProgram = program;
        return true;
    }
    return false;
}
  • 同一 program 不重复 useProgram
  • 切换时返回 true,未切换返回 false(完整版上层可据此决定是否重绑 uniform)

在 WebGLRendererMini.setProgram 中会调用useProgram :

ini 复制代码
state.useProgram( program.program );

4. viewport --- 视口设置

scss 复制代码
// 设置视口,如果当前视口与传入视口相同,则不进行操作
function viewport( viewport ) {
    if ( currentViewport.equals( viewport ) === false ) {
        gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
        currentViewport.copy( viewport );
    }
}

viewport 的概念是在画布中确定一个矩形区域,webgl 会只在这个区域中绘画。

5. 对外接口

css 复制代码
return {
    buffers: {
        color: colorBuffer,
    },
    useProgram: useProgram,
    viewport: viewport,
};

总结

WebGLStateMini 可以在 JavaScript 侧缓存当前 GL 状态,只在变化时才调用底层 API,避免重复设置。

下一章我们会说mini版的WebGLProperties。

相关推荐
沧沧凉凉9 小时前
一段需求、零素材,Claude Code 派了 33 个代理给我做了个 3D 动作游戏
游戏·ai编程·three.js
福兮说10 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
郑州光合科技余经理10 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
小呆呆66611 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
Dovis(誓平步青云)11 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
码艺-Alimjan12 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
可乐鸡翅yeah_13 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
IT_陈寒13 小时前
Vite静态资源导入这个坑我帮你们踩过了
前端·人工智能·后端
广州华水科技13 小时前
大坝安全监测解决方案:单北斗GNSS形变监测系统应用与维护
前端
yivifu14 小时前
中文古籍电子书注释集成
前端·javascript·python·beautifulsoup·epub