You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebGL顶点着色器编译报错:含main()却提示缺失

问题:Three.js着色器加载为空导致"Missing main()"错误

报错信息

three.js:12525 THREE.WebGLProgram: Shader Error 0 - VALIDATE_STATUS false

Program Info Log: Vertex shader is not compiled.

ERROR: Missing main()

ERROR: Missing main()

问题背景

一个1-2年前可正常运行的Three.js着色器测试应用,现在在Chrome、Firefox浏览器及Windows 10设备上均出现上述报错。检查发现,虽然着色器文件中明确包含main()函数,但控制台打印出的着色器内容为空,而本地Python服务器日志显示着色器文件请求已成功返回200:

::1 - - [14/Nov/2022 02:28:41] "GET /shaders/default.vert HTTP/1.1" 200 -
::1 - - [14/Nov/2022 02:28:41] "GET /shaders/default.frag HTTP/1.1" 200 -

最小复现示例

本地服务器启动命令

python -m http.server 8000

index.html

<html>
    <head>
        <title>Test tree.js app</title>
        <style>
            body { margin: 0; }
            canvas { width: 100%; height: 100% }
        </style>
    </head>
    <body>
        <script src="https://threejs.org/build/three.js"></script>
        <script src="main.js"></script>
    </body>
</html>

main.js

RESOURCES = [
  ["vert_shader", "http://localhost:8000/shaders/default.vert"],
  ["frag_shader", "http://localhost:8000/shaders/default.frag"]
];

function initialise_scene(resources) {
  var scene = new THREE.Scene();
  scene.fog = new THREE.FogExp2(0x7c7c7c, 0.002);
  
  var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
  camera.position.z = 30;

  var renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setClearColor(scene.fog.color, 1);
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  function defaultShader(r, g, b) {
    return new THREE.ShaderMaterial({
      uniforms: {
        color: {value: new THREE.Vector3(r, g, b)}
      },
      vertexShader: resources["vert_shader"],
      fragmentShader: resources["frag_shader"]
    });
  };

  geometry = new THREE.BoxGeometry(4, 4, 4);
  // material = new THREE.MeshLambertMaterial({ color: 0x000000 });
  material = defaultShader(0.0, 0.0, 0.0);
  cube = new THREE.Mesh(geometry, material);
  cube.position.set(-10, 5, -5);
  scene.add(cube);

  renderer.render(scene, camera);
}

function load_resources() {
  var promises = []

  for(let r of RESOURCES) {
    promises.push(fetch(r[1], {
      mode: 'no-cors'
    })
    .then(res => res.text()))
  }

  return Promise.all(promises).then(function(res) {
    let resources = {}
    for(let i in RESOURCES) {
      resources[RESOURCES[i][0]] = res[i]
    }
    return resources
  })
}

load_resources().then(res => initialise_scene(res))

shaders/default.vert

void main() {
}

shaders/default.frag

uniform vec3 color;

void main() {
  gl_FragColor = vec4(color, 1.0);
}

问题根源

  1. fetch跨域模式错误:使用mode: 'no-cors'发起请求时,浏览器会将响应标记为opaque response,无法读取响应内容,即使服务器返回200,res.text()也会返回空字符串,导致Three.js拿到空的着色器代码,从而报错"Missing main()"。
  2. 顶点着色器功能缺失:当前顶点着色器的main()函数为空,没有输出顶点位置,即使加载成功也无法渲染出物体。

解决方案

1. 修正fetch请求配置

移除mode: 'no-cors',本地页面和服务器同域,无需跨域模式:

function load_resources() {
  var promises = []

  for(let r of RESOURCES) {
    // 移除no-cors模式
    promises.push(fetch(r[1])
      .then(res => res.text()))
  }

  return Promise.all(promises).then(function(res) {
    let resources = {}
    for(let i in RESOURCES) {
      resources[RESOURCES[i][0]] = res[i]
    }
    return resources
  })
}

2. 完善顶点着色器

补充顶点位置的输出逻辑,确保WebGL能正确处理顶点数据:

void main() {
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

额外优化建议

  • 使用相对路径加载资源,避免硬编码localhost,提高代码灵活性:
    RESOURCES = [
      ["vert_shader", "./shaders/default.vert"],
      ["frag_shader", "./shaders/default.frag"]
    ];
    
  • 添加请求错误处理,便于排查资源加载失败问题:
    promises.push(fetch(r[1])
      .then(res => {
        if (!res.ok) throw new Error(`资源请求失败,状态码:${res.status}`);
        return res.text();
      })
      .catch(err => {
        console.error('加载着色器出错:', err);
        throw err; // 继续抛出错误,避免后续逻辑执行
      })
    )
    

内容的提问来源于stack exchange,提问作者Talos Asimov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 11:10:38