mirror of
https://github.com/tengge1/ShadowEditor.git
synced 2026-01-25 15:08:11 +00:00
使用GPU反算世界坐标
This commit is contained in:
parent
f3bd5373a9
commit
16b0ec7ba8
0
ShadowEditor.Web/src/controls/ControlsManager.js
Normal file
0
ShadowEditor.Web/src/controls/ControlsManager.js
Normal file
@ -1,86 +0,0 @@
|
||||
import BaseEvent from './BaseEvent';
|
||||
import DepthVertexShader from './shader/depth_vertex.glsl';
|
||||
import DepthFragmentShader from './shader/depth_fragment.glsl';
|
||||
|
||||
/**
|
||||
* 使用GPU进行碰撞
|
||||
* @author tengge / https://github.com/tengge1
|
||||
* @param {*} app 应用程序
|
||||
*/
|
||||
function GPUPickEvent(app) {
|
||||
BaseEvent.call(this, app);
|
||||
|
||||
this.offsetX = 0;
|
||||
this.offsetY = 0;
|
||||
|
||||
this.onMouseMove = this.onMouseMove.bind(this);
|
||||
this.onAfterRender = this.onAfterRender.bind(this);
|
||||
}
|
||||
|
||||
GPUPickEvent.prototype = Object.create(BaseEvent.prototype);
|
||||
GPUPickEvent.prototype.constructor = GPUPickEvent;
|
||||
|
||||
GPUPickEvent.prototype.start = function () {
|
||||
app.on(`mousemove.${this.id}`, this.onMouseMove);
|
||||
app.on(`afterRender.${this.id}`, this.onAfterRender);
|
||||
};
|
||||
|
||||
GPUPickEvent.prototype.stop = function () {
|
||||
app.on(`mousemove.${this.id}`, null);
|
||||
app.on(`afterRender.${this.id}`, null);
|
||||
};
|
||||
|
||||
GPUPickEvent.prototype.onMouseMove = function (event) {
|
||||
if (event.target !== app.editor.renderer.domElement) {
|
||||
return;
|
||||
}
|
||||
this.offsetX = event.offsetX;
|
||||
this.offsetY = event.offsetY;
|
||||
};
|
||||
|
||||
GPUPickEvent.prototype.onAfterRender = function () {
|
||||
let world = new THREE.Vector3();
|
||||
return function () {
|
||||
let { scene, camera, renderer } = app.editor;
|
||||
const { width, height } = renderer.domElement;
|
||||
|
||||
if (this.init === undefined) {
|
||||
this.init = true;
|
||||
this.material = new THREE.ShaderMaterial({
|
||||
vertexShader: DepthVertexShader,
|
||||
fragmentShader: DepthFragmentShader
|
||||
});
|
||||
this.renderTarget = new THREE.WebGLRenderTarget(width, height);
|
||||
this.pixel = new Uint8Array(4);
|
||||
}
|
||||
|
||||
// 记录旧属性
|
||||
const oldOverrideMaterial = scene.overrideMaterial;
|
||||
const oldRenderTarget = renderer.getRenderTarget();
|
||||
|
||||
// 更换深度材质
|
||||
scene.overrideMaterial = this.material;
|
||||
renderer.setRenderTarget(this.renderTarget);
|
||||
renderer.clear();
|
||||
|
||||
// 读取深度
|
||||
this.pixel.set([0, 0, 0, 0]);
|
||||
renderer.render(scene, camera);
|
||||
renderer.readRenderTargetPixels(this.renderTarget, this.offsetX, height - this.offsetY, 1, 1, this.pixel);
|
||||
|
||||
let depth = (this.pixel[0] * 65535 + this.pixel[1] * 255 + this.pixel[2]) / 16777215 * 80 - 1;
|
||||
|
||||
world.set(
|
||||
this.offsetX / width * 2 - 1,
|
||||
- this.offsetY / height * 2 + 1,
|
||||
depth
|
||||
);
|
||||
world.unproject(camera);
|
||||
|
||||
// 还原原来的属性
|
||||
scene.overrideMaterial = oldOverrideMaterial;
|
||||
renderer.setRenderTarget(oldRenderTarget);
|
||||
};
|
||||
}();
|
||||
|
||||
export default GPUPickEvent;
|
||||
@ -1,12 +1,14 @@
|
||||
import BaseEvent from './BaseEvent';
|
||||
import PickVertexShader from './shader/pick_vertex.glsl';
|
||||
import PickFragmentShader from './shader/pick_fragment.glsl';
|
||||
import DepthVertexShader from './shader/depth_vertex.glsl';
|
||||
import DepthFragmentShader from './shader/depth_fragment.glsl';
|
||||
import MeshUtils from '../utils/MeshUtils';
|
||||
|
||||
let maxHexColor = 1;
|
||||
|
||||
/**
|
||||
* 使用GPU进行碰撞
|
||||
* 使用GPU选取物体和计算鼠标世界坐标
|
||||
* @author tengge / https://github.com/tengge1
|
||||
*/
|
||||
function GPUPickEvent() {
|
||||
@ -48,6 +50,9 @@ GPUPickEvent.prototype.onMouseMove = function (event) {
|
||||
this.offsetY = event.offsetY;
|
||||
};
|
||||
|
||||
/**
|
||||
* 由于需要较高性能,所以尽量不要拆分函数。
|
||||
*/
|
||||
GPUPickEvent.prototype.onAfterRender = function () {
|
||||
if (!this.isIn) {
|
||||
return;
|
||||
@ -57,8 +62,13 @@ GPUPickEvent.prototype.onAfterRender = function () {
|
||||
|
||||
if (this.init === undefined) {
|
||||
this.init = true;
|
||||
this.depthMaterial = new THREE.ShaderMaterial({
|
||||
vertexShader: DepthVertexShader,
|
||||
fragmentShader: DepthFragmentShader
|
||||
});
|
||||
this.renderTarget = new THREE.WebGLRenderTarget(width, height);
|
||||
this.pixel = new Uint8Array(4);
|
||||
this.world = new THREE.Vector3();
|
||||
}
|
||||
|
||||
// 记录旧属性
|
||||
@ -66,6 +76,8 @@ GPUPickEvent.prototype.onAfterRender = function () {
|
||||
const oldOverrideMaterial = scene.overrideMaterial;
|
||||
const oldRenderTarget = renderer.getRenderTarget();
|
||||
|
||||
// ---------------------------- 1. 使用GPU判断选中的物体 -----------------------------------
|
||||
|
||||
scene.background = null; // 有背景图,可能导致提取的颜色不准
|
||||
scene.overrideMaterial = null;
|
||||
renderer.setRenderTarget(this.renderTarget);
|
||||
@ -129,6 +141,29 @@ GPUPickEvent.prototype.onAfterRender = function () {
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------- 2. 使用GPU反算世界坐标 ----------------------------------
|
||||
|
||||
scene.overrideMaterial = this.material;
|
||||
|
||||
renderer.clear();
|
||||
renderer.render(scene, camera);
|
||||
renderer.readRenderTargetPixels(this.renderTarget, this.offsetX, height - this.offsetY, 1, 1, this.pixel);
|
||||
|
||||
let depth = (this.pixel[0] * 65535 + this.pixel[1] * 255 + this.pixel[2]) / 0xffffff;
|
||||
|
||||
if (this.pixel[3] === 0) {
|
||||
depth = -depth;
|
||||
}
|
||||
|
||||
this.world.set(
|
||||
this.offsetX / width * 2 - 1,
|
||||
- this.offsetY / height * 2 + 1,
|
||||
depth
|
||||
);
|
||||
this.world.unproject(camera);
|
||||
|
||||
// console.log(`${this.pixel[0]}, ${this.pixel[1]}, ${this.pixel[2]}, ${depth}, ${this.world.x}, ${this.world.y}, ${this.world.z}`);
|
||||
|
||||
// 还原原来的属性
|
||||
scene.background = oldBackground;
|
||||
scene.overrideMaterial = oldOverrideMaterial;
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
precision highp float;
|
||||
|
||||
varying float depth;
|
||||
|
||||
void main() {
|
||||
float hex = abs(depth) * 16777215.0;
|
||||
float hex = abs(clamp(depth, -1.0, 1.0)) * 16777215.0; // 0xffffff
|
||||
|
||||
float r = floor(hex / 65535.0);
|
||||
float g = floor((hex - r * 65535.0) / 255.0);
|
||||
float b = floor(hex - r * 65535.0 - g * 255.0);
|
||||
float a = sign(depth) >= 0.0 ? 1.0 : 0.0; // depth大于等于0,为1.0;小于0,为0.0。
|
||||
|
||||
gl_FragColor = vec4(r / 255.0, g / 255.0, b / 255.0, 1.0);
|
||||
gl_FragColor = vec4(r / 255.0, g / 255.0, b / 255.0, a);
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
precision highp float;
|
||||
|
||||
varying float depth;
|
||||
|
||||
void main() {
|
||||
vec4 transformed = modelViewMatrix * vec4(position, 1.0);
|
||||
gl_Position = projectionMatrix * transformed;
|
||||
depth = transformed.z;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||
depth = gl_Position.z;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user