createShader仅创建空着色器对象,不加载或编译GLSL代码;真正使着色器生效需依次调用shaderSource注入源码和compileShader执行编译,缺一不可。

createShader 本身不编译、不加载代码,只创建空对象;真正让着色器“活起来”的是 shaderSource + compileShader 这两步,缺一不可。
createShader 返回 null 怎么办
这几乎一定是上下文或参数问题,不是 GLSL 写错了:
-
gl对象为null—— 检查canvas.getContext('webgl')是否成功,WebGL 不可用时会返回null(可 fallback 到'webgl2') - 传了错误的 type —— 只能是
gl.VERTEX_SHADER或gl.FRAGMENT_SHADER,写成字符串"vertex"、数字35633或拼错变量名都会失败 - 调用时机太早 —— 比如在
canvas元素还没挂载到 DOM 时就尝试获取上下文
shaderSource 之后必须立刻 compileShader
shaderSource 只是把字符串塞进着色器对象,不做任何校验;compileShader 才真正解析和编译 GLSL。顺序反了或漏掉 compileShader,后续 attachShader 会静默失败。
-
shaderSource的第二个参数必须是纯字符串,不能是<script>元素本身,得用.textContent或.innerHTML提取 - 重复调用
shaderSource会覆盖源码,但不会自动重新编译 —— 必须手动再调一次compileShader - WebGL 1 要求片元着色器必须声明
precision(如precision mediump float;),漏写会导致编译失败
编译失败时怎么定位错误
getShaderParameter(shader, gl.COMPILE_STATUS) 是唯一可靠的判断依据,不要靠肉眼猜:
立即学习“前端免费学习笔记(深入)”;
- 编译失败时,
gl.getShaderInfoLog(shader)才可能有有效错误信息(比如第 3 行缺少分号、gl_FragColor写成gl_Frag_Color) - 编译成功时,
getShaderInfoLog可能返回空字符串,别把它当常规日志打印 - 常见低级错误:顶点着色器没写
gl_Position、片元着色器没写gl_FragColor、GLSL 版本混用(WebGL 1 不支持out vec4 fragColor)
compileShader 成功后还不能直接渲染
编译成功的着色器对象只是“就绪”,不是“可用”。WebGL 要求你必须把它们组合成一个 WebGLProgram:
- 先
gl.createProgram(),再gl.attachShader(program, vs)和gl.attachShader(program, fs) - 然后
gl.linkProgram(program)—— 链接失败(比如 attribute 名不匹配、varying 类型不一致)比编译失败更难 debug,必须检查gl.getProgramParameter(program, gl.LINK_STATUS) -
gl.useProgram(program)后才能开始绘图;忘记这步,GPU 会继续用上一个 program,结果常是黑屏或旧画面残留
最容易被忽略的是链接阶段的检查 —— 编译通过不代表能用,attribute 名拼错一个字母、varying 类型在顶点和片元中不一致,都会导致链接失败且无明显报错,最终画面全黑。



















