У меня есть проблема с мерцанием THREE.Points в зависимости от их УФ координат, как показано в следующих codepen: http://codepen.io/anon/pen/qrdQeY?editors=0010мерцанием THREE.Points на основании положения камеры и текстурных координат, но только на Nvidia карты
код в codepen конденсируется вниз как можно больше (171 строк), но суммировать то, что я делаю:
- рендеринга спрайтов с использованием THREE.Points
- BufferGeometry содержит индекс spritesheet и положение для каждого спрайта
- RawShaderMaterial с пользовательскими вершинных и пиксельных шейдеров для поиска до УФ-координаты спрайта для данного индекса
- 128x128px spritesheet с 4x4 клеток содержит спрайты
Вот код:
/// FRAGMENT SHADER ===========================================================
const fragmentShader = `
precision highp float;
uniform sampler2D spritesheet;
// number of spritesheet subdivisions both vertically and horizontally
// e.g. for a 4x4 spritesheet this number is 4
uniform float spritesheetSubdivisions;
// vParams[i].x = sprite index
// vParams[i].z = sprite alpha
varying vec3 vParams;
/**
* Maps regular UV coordinates spanning the entire spritesheet
* to a specific sprite within the spritesheet based on the given index,
* which points into a spritesheel cell (depending on spritesheetSubdivisions
* and assuming that the spritesheet is regular and square).
*/
vec2 spriteIndexToUV(float idx, vec2 uv) {
float cols = spritesheetSubdivisions;
float rows = spritesheetSubdivisions;
float x = mod(idx, cols);
float y = floor(idx/cols);
return vec2(x/cols + uv.x/cols, 1.0 - (y/rows + (uv.y)/rows));
}
void main() {
vec2 uv = spriteIndexToUV(vParams.x, gl_PointCoord);
vec4 diffuse = texture2D(spritesheet, uv);
float alpha = diffuse.a * vParams.z;
if (alpha < 0.5) discard;
gl_FragColor = vec4(diffuse.xyz, alpha);
}
`
// VERTEX SHADER ==============================================================
const vertexShader = `
precision highp float;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform float size;
uniform float scale;
attribute vec3 position;
attribute vec3 params; // x = sprite index, y = unused, z = sprite alpha
attribute vec3 color;
varying vec3 vParams;
void main() {
vParams = params;
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * mvPosition;
gl_PointSize = size * (scale/- mvPosition.z);
}
`
// THREEJS CODE ===============================================================
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({canvas: document.querySelector("#mycanvas")});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xf0f0f0)
const pointGeometry = new THREE.BufferGeometry()
pointGeometry.addAttribute("position", new THREE.BufferAttribute(new Float32Array([
-1.5, -1.5, 0,
-0.5, -1.5, 0,
0.5, -1.5, 0,
1.5, -1.5, 0,
-1.5, -0.5, 0,
-0.5, -0.5, 0,
0.5, -0.5, 0,
1.5, -0.5, 0,
-1.5, 0.5, 0,
-0.5, 0.5, 0,
0.5, 0.5, 0,
1.5, 0.5, 0,
-1.5, 1.5, 0,
-0.5, 1.5, 0,
0.5, 1.5, 0,
1.5, 1.5, 0,
]), 3))
pointGeometry.addAttribute("params", new THREE.BufferAttribute(new Float32Array([
0, 0, 1, // sprite index 0 (row 0, column 0)
1, 0, 1, // sprite index 1 (row 0, column 1)
2, 0, 1, // sprite index 2 (row 0, column 2)
3, 0, 1, // sprite index 3 (row 0, column 4)
4, 0, 1, // sprite index 4 (row 1, column 0)
5, 0, 1, // sprite index 5 (row 1, column 1)
6, 0, 1, // ...
7, 0, 1,
8, 0, 1,
9, 0, 1,
10, 0, 1,
11, 0, 1,
12, 0, 1,
13, 0, 1,
14, 0, 1,
15, 0, 1
]), 3))
const img = document.querySelector("img")
const texture = new THREE.TextureLoader().load(img.src);
const pointMaterial = new THREE.RawShaderMaterial({
transparent: true,
vertexShader: vertexShader,
fragmentShader: fragmentShader,
uniforms: {
spritesheet: {
type: "t",
value: texture
},
spritesheetSubdivisions: {
type: "f",
value: 4
},
size: {
type: "f",
value: 1
},
scale: {
type: "f",
value: window.innerHeight/2
}
}
})
const points = new THREE.Points(pointGeometry, pointMaterial)
scene.add(points)
const render = function (timestamp) {
requestAnimationFrame(render);
camera.position.z = 5 + Math.sin(timestamp/1000.0)
renderer.render(scene, camera);
};
render();
// resize viewport
window.addEventListener('resize', onWindowResize, false);
function onWindowResize(){
camera.aspect = window.innerWidth/window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
Если у вас есть карта Nvidia, вы увидите мерцание трех спрайтов, когда камера перемещается вперед и назад по оси Z. На интегрированных графических чипах Intel проблема не возникает.
Я не уверен, как решить эту проблему. Поврежденные uv-координаты кажутся случайными. Я был бы благодарен за любые указатели.
Интересно! Я могу подтвердить различное поведение (на настольном компьютере Macbook с Intel HD). Вы пытались использовать * highp * для шейдеров? Поскольку это * подсказка *, интерпретация по умолчанию может быть разной. Я не могу с легкостью сказать из вашего кода, в какой степени отображаются разные слои, поскольку они прозрачны, а также на стороне процессора, которая может быть связана между тремя группами. –
Спасибо, что посмотрели! Спринты слегка визуализируются (z = 0,12 против z = 0 рельефа). Увеличение этого ничего не меняет. Также изменение свойства прозрачности материала на значение false не помогает мерцанию. Шейдеры используют highp, насколько я могу судить.Или есть что-то еще, что вам нужно сделать, кроме добавления «precision highp»? в верхней части шейдера? – Bunkerbewohner
N/m мой последний комментарий относительно «highp», только что заметил, что шейдер, который я связал, использует «mediump». К сожалению, изменение этого параметра на «highp» тоже не помогает. – Bunkerbewohner