Does THREE cull geometry?

I use raw shader material to draw a couple of line segments, so the vertex shader assigns positions directly without using view-model-projection matrices or geometry values.

I thought in this situation it doesn’t matter if I assign position to the lines object or not but it turns out that for coordinates bigger that certain value lines are not drawn anymore, here is the code:

<canvas id="main_canvas" style="border: solid 1px red;" width=600 height=600></canvas>

<script type="x-shader/x-vertex" id="vs">
  #version 100
  attribute vec4 clr;
  attribute float id;
  varying vec4 vclr;
  
  void main() {
		
    vec2 pos;
    
    if(id < 1.0)
    	pos = vec2(-1.0, 1.0);
    else if(id < 2.0)
    	pos = vec2(-0.5, 0.5);
    else if(id < 3.0)
    	pos = vec2(0.0, 0.0);
    else 
    	pos = vec2(1.0, 0.0);
    
    gl_Position = vec4(pos, 0.0, 1.0);
    
    vclr = clr;
  }
</script>

<script type='x-shader/x-fragment' id='fs'>
	#version 100
  #ifdef GL_FRAGMENT_PRECISION_HIGH
  	precision highp float;
  #else
    precision mediump float;
  #endif
  
  varying vec4 vclr;

  void main() {
  
    gl_FragColor = vclr;
  }
</script>

<script type="module">
    import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.126/build/three.module.js'

const get = (id) => document.getElementById(id);

const canvas = get('main_canvas');
const [w2, h2] = [canvas.width/2, canvas.height/2];
const renderer = new THREE.WebGLRenderer({
  antialias: false,
  alpha: true,
  canvas,
});
renderer.setPixelRatio(window.devicePixelRatio);

const [near, far] = [0, 1000];
const camera = new THREE.OrthographicCamera(-w2, w2, h2, -h2, near, far);

const points = [];
points.push( new THREE.Vector3( 0, 0, 0 ));
points.push( new THREE.Vector3( -100, -100, 0 ));

points.push( new THREE.Vector3( 100, 100, 0 ));
points.push( new THREE.Vector3( 220, 250, 0 ));

const geo = new THREE.BufferGeometry().setFromPoints( points );
const mat = new THREE.RawShaderMaterial({
    vertexShader: get('vs').textContent,
    fragmentShader: get('fs').textContent,
    transparent: true,
  });
  
const clr = [ // r,g,b,a
	1, 0, 0, 0.2,
  1, 0, 0, 1.0,
  
  0, 1, 0, 0.3,
  1, 1, 0, 1.0,
];  

const id = [0,1,2,3];

geo.setAttribute('clr', new THREE.Float32BufferAttribute(clr, 4));  
geo.setAttribute('id', new THREE.Float32BufferAttribute(id, 1)); 

const lines = new THREE.LineSegments( geo, mat );

lines.position.set(477.1, 0, -1237.1);

const scene = new THREE.Scene()
  .add(lines);

renderer.render(scene, camera);
</script>

In this example

lines.position.set(477.1, 0, -1237.1);

is the max xz coordinates at which lines are drawn, if I change it to

lines.position.set(477.2, 0, -1237.2);

they disappear.

Why is it happening this way, does THREE cull geometry before passing it to the shader or performs any checks similar to what the 3D pipeline does?

Thank you!

https://jsfiddle.net/tfoller/te4620x7/35/

Yes. If you want to turn this off you can set the frustumCulled property of an object to false.

1 Like