Я пытаюсь обнаружить, где в текстуре на объекте пользователь щелкнул, чтобы я мог перерисовать текстуру в ответ.Выбор координаты текстуры
Я знаю, что я могу визуализировать объекты с цветной текстурой отдельной целью рендеринга и использовать gl.readPixels, чтобы увидеть, какой закодированный пиксель был нажат, а затем вычислить, к чему мои координаты X и Y должны находиться в текстуры.
Я, кажется, могу надежно выполнить это для оси Y, но не по оси X.
Это мои (посторонние биты кода удалены) Three.js установки:
var canvas = document.getElementByID("output"),
renderer = new THREE.WebGLRenderer({
canvas: canvas,
alpha: true,
antialias: true
}),
back = new THREE.WebGLRenderTarget(canvas.width, canvas.height),
scene = new THREE.Scene(),
pickingScene = new THREE.Scene(),
pickingPixelBuffer = new Uint8Array(4),
camera = new THREE.PerspectiveCamera(50, canvas.width/canvas.height, 0.1, 1000),
textureWidth = 1024,
textureHeight = 1024,
texture = generateTexture(textureWidth, textureHeight),
pickingTexture = generatePickingTexture(textureWidth, textureHeight),
obj = textured(shell(w, 5, 10), texture),
objPicker = textured(shell(w, 5, 10), pickingTexture);
back.generateMipmaps = false;
scene.add(camera);
scene.add(obj);
pickingScene.add(objPicker);
Так что для объекта, как это:
текстура сбор заканчивается, глядя, как это:
Функция generateTexture
на самом деле не так важна. textured
функция просто стенография для нанесения текстуры на геометрию объекта:
function textured(geometry, txt){
var material = new THREE.MeshBasicMaterial({
color: 0xffffff,
map: txt,
transparent: false,
shading: THREE.FlatShading,
side: THREE.DoubleSide
});
var obj = new THREE.Mesh(geometry, material);
return obj;
}
и функция generatePickingTexture
таким образом:
function generatePickingTexture(w, h){
var canvas = document.createElement("canvas");
canvas.width = w;
canvas.height = h;
var texture = new THREE.Texture(canvas);
var gfx = texture.image.getContext("2d"),
l = w * h,
pixels = gfx.createImageData(w, h);
for(var i = 0, p = 0;
i < l;
++i, p += 4){
pixels.data[p] = (0xff0000 & i) >> 16;
pixels.data[p+1] = (0x00ff00 & i) >> 8;
pixels.data[p+2] = 0x0000ff & i;
pixels.data[p+3] = 0xff;
}
gfx.putImageData(pixels, 0, 0);
texture.needsUpdate = true;
return texture;
}
Тогда я пытаюсь выполнить комплектование:
function pick(){
renderer.render(pickingScene, camera, back, true);
var gl = renderer.getContext();
gl.readPixels(pointerX, canvas.height - pointerY, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pickingPixelBuffer);
var i = (pickingPixelBuffer[0] << 16) |
(pickingPixelBuffer[1] << 8) |
pickingPixelBuffer[2],
// x = i % textureWidth,
x = (i - Math.floor(textureWidth/512) * 256) % textureWidth, // EDIT2: this is the hack
y = i/textureWidth;
console.log(x, y);
}
Как я уже сказал, координата y отлично работает. Но координата x выключена. Когда я перетаскиваю мышью по экрану, x-координаты переходят вправо, прыгая примерно на 1/4 ширины текстуры. Когда я перетаскиваю мышь по экрану, если я могу избежать вертикального движения мыши, координата x перемещается с правильным смещением, но не находится в нужном месте. Кажется, что он прыгает на место каждый раз, когда я ударяю одну из 1/4 маркировки.
С его 1/4th, кажется вероятным, что моя математика для генерации текстуры неверна. Но для моей жизни я не вижу этого.
EDIT: действительно, если я ограничу свою текстуру только шириной в 256 пикселей, она отлично работает.
EDIT2: Я выяснил взломанную функцию
pick
, которая устраняет проблему, но я не понимаю, почему она работает.
EDIT3: Хорошо, «работает» под условием, что объект имеет коэффициент отображения 1 к 1 для экрана. Есть еще некоторые проблемы с разными ориентациями, но это не связано с этой другой проблемой. Я подозреваю, что это связано с повторной выборкой текстуры.
EDIT4: это настройки фильтрации текстуры по умолчанию.