#746 A lot of changes to Geometry. Started integrating RTE with the viewer
This commit is contained in:
@@ -7,16 +7,18 @@ export default class Sandbox {
|
||||
private pane: Pane
|
||||
private tabs: any
|
||||
|
||||
private static urlParams = {
|
||||
public static urlParams = {
|
||||
url: 'https://latest.speckle.dev/streams/010b3af4c3/objects/a401baf38fe5809d0eb9d3c902a36e8f'
|
||||
}
|
||||
|
||||
private static sceneParams = {
|
||||
public static sceneParams = {
|
||||
worldSize: {x: 0, y: 0, z: 0},
|
||||
worldOrigin: {x:0, y:0, z:0},
|
||||
exposure: 0.4,
|
||||
tonemapping: 'Linear'
|
||||
}
|
||||
|
||||
public constructor(viewer: IViewer) {
|
||||
public constructor(viewer: Viewer) {
|
||||
this.viewer = viewer
|
||||
this.pane = new Pane({ title: 'Sandbox', expanded: true })
|
||||
this.pane['containerElem_'].style.width = "300px";
|
||||
@@ -30,6 +32,10 @@ export default class Sandbox {
|
||||
});
|
||||
}
|
||||
|
||||
public refresh() {
|
||||
this.pane.refresh();
|
||||
}
|
||||
|
||||
public makeGenericUI() {
|
||||
this.tabs.pages[0].addInput(Sandbox.urlParams, 'url', {
|
||||
title: 'url'
|
||||
@@ -76,6 +82,40 @@ export default class Sandbox {
|
||||
}
|
||||
|
||||
makeSceneUI() {
|
||||
const worldFolder = this.tabs.pages[1].addFolder({
|
||||
title: "World",
|
||||
expanded: true
|
||||
});
|
||||
worldFolder.addInput(Sandbox.sceneParams.worldSize, 'x', {
|
||||
disabled: true,
|
||||
label: "Size-x",
|
||||
step: 0.00000001
|
||||
});
|
||||
worldFolder.addInput(Sandbox.sceneParams.worldSize, 'y', {
|
||||
disabled: true,
|
||||
label: "Size-y",
|
||||
step: 0.00000001
|
||||
});
|
||||
worldFolder.addInput(Sandbox.sceneParams.worldSize, 'z', {
|
||||
disabled: true,
|
||||
label: "Size-z",
|
||||
step: 0.00000001
|
||||
});
|
||||
worldFolder.addSeparator();
|
||||
worldFolder.addInput(Sandbox.sceneParams.worldOrigin, 'x', {
|
||||
disabled: true,
|
||||
label: "Origin-x"
|
||||
});
|
||||
worldFolder.addInput(Sandbox.sceneParams.worldOrigin, 'y', {
|
||||
disabled: true,
|
||||
label: "Origin-y"
|
||||
});
|
||||
worldFolder.addInput(Sandbox.sceneParams.worldOrigin, 'z', {
|
||||
disabled: true,
|
||||
label: "Origin-z"
|
||||
});
|
||||
|
||||
this.tabs.pages[1].addSeparator();
|
||||
const postFolder = this.tabs.pages[1].addFolder({
|
||||
title: "Post",
|
||||
expanded: true
|
||||
|
||||
@@ -11,18 +11,26 @@ if (!container) {
|
||||
const viewer = new Viewer(container)
|
||||
await viewer.init()
|
||||
|
||||
const sandbox = new Sandbox(viewer)
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
viewer.onWindowResize()
|
||||
})
|
||||
|
||||
const sandbox = new Sandbox(viewer)
|
||||
sandbox.makeGenericUI()
|
||||
sandbox.makeSceneUI()
|
||||
// Load demo object
|
||||
sandbox.loadUrl('https://latest.speckle.dev/streams/921741b30b/commits/c5acd4ff91?c=%5B147162.48107,6396783.94314,18.1266,147140.22466,6396758.05514,9.41576,0,1%5D')
|
||||
|
||||
viewer.on('load-progress', (a: { progress: number; id: string; url: string }) => {
|
||||
if (a.progress >= 1) {
|
||||
viewer.onWindowResize()
|
||||
}
|
||||
})
|
||||
|
||||
viewer.on('load-complete', ()=> {
|
||||
Object.assign(Sandbox.sceneParams.worldSize, viewer.worldSize);
|
||||
Object.assign(Sandbox.sceneParams.worldOrigin, viewer.worldOrigin);
|
||||
sandbox.refresh();
|
||||
})
|
||||
|
||||
sandbox.makeGenericUI()
|
||||
sandbox.makeSceneUI()
|
||||
// Load demo object
|
||||
sandbox.loadUrl('https://latest.speckle.dev/streams/3ed8357f29/commits/b21fb0dcf7')
|
||||
|
||||
@@ -3,9 +3,10 @@ import debounce from 'lodash.debounce'
|
||||
import SceneObjects from './SceneObjects'
|
||||
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js'
|
||||
import { Line2 } from 'three/examples/jsm/lines/Line2.js'
|
||||
import { Vector2 } from 'three'
|
||||
import { Matrix4, Vector2, Vector3 } from 'three'
|
||||
import { GEOMETRY_LINES_AS_TRIANGLES } from './converter/Geometry'
|
||||
|
||||
import SpeckleStandardMaterial from './materials/SpeckleStandardMaterial'
|
||||
import SpeckleLineMaterial from './materials/SpeckleLineMaterial'
|
||||
/**
|
||||
* Manages objects and provides some convenience methods to focus on the entire scene, or one specific object.
|
||||
*/
|
||||
@@ -17,7 +18,7 @@ export default class SceneObjectManager {
|
||||
|
||||
this.sceneObjects = new SceneObjects(viewer)
|
||||
|
||||
this.solidMaterial = new THREE.MeshStandardMaterial({
|
||||
this.solidMaterial = new SpeckleStandardMaterial({
|
||||
color: 0x8d9194,
|
||||
emissive: 0x0,
|
||||
roughness: 1,
|
||||
@@ -362,7 +363,7 @@ export default class SceneObjectManager {
|
||||
makeLineMaterial() {
|
||||
let lineMaterial
|
||||
if (GEOMETRY_LINES_AS_TRIANGLES) {
|
||||
lineMaterial = new LineMaterial({
|
||||
lineMaterial = new SpeckleLineMaterial({
|
||||
color: 0x7f7f7f,
|
||||
linewidth: 1, // in world units with size attenuation, pixels otherwise
|
||||
worldUnits: false,
|
||||
|
||||
@@ -44,6 +44,7 @@ export default class SceneObjects {
|
||||
// When the `appliedFilter` is null, scene will contain `allObjects`. Otherwise, `filteredObjects`
|
||||
// This is to optimize the no-filter usecase, so we don't make an unnecessary clone of all the objects
|
||||
this.objectsInScene = this.allObjects
|
||||
|
||||
this.scene.add(this.allObjects)
|
||||
|
||||
this.isBusy = true
|
||||
@@ -289,7 +290,8 @@ export default class SceneObjects {
|
||||
) {
|
||||
// if ( mesh.type === 'Line' ) continue
|
||||
// if ( groupedObjects.children.length >= 2 ) continue
|
||||
groupedObjects.add(mesh.clone())
|
||||
const clone = mesh.clone()
|
||||
groupedObjects.add(clone)
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,13 @@ import InteractionHandler from './InteractionHandler'
|
||||
import CameraHandler from './context/CameraHanlder'
|
||||
|
||||
import SectionBox from './SectionBox'
|
||||
import { Clock, CubeCamera } from 'three'
|
||||
import { Box3, Clock, CubeCamera, Vector3 } from 'three'
|
||||
import { Scene } from 'three'
|
||||
import { WebGLRenderer } from 'three'
|
||||
import { Assets } from './Assets'
|
||||
import { Optional } from '../helpers/typeHelper'
|
||||
import { DefaultViewerParams, IViewer, ViewerParams } from '../IViewer'
|
||||
import { World } from './World'
|
||||
|
||||
export class Viewer extends EventEmitter implements IViewer {
|
||||
private clock: Clock
|
||||
@@ -34,6 +35,22 @@ export class Viewer extends EventEmitter implements IViewer {
|
||||
|
||||
public static Assets: Assets
|
||||
|
||||
private _worldSize: Box3 = new Box3()
|
||||
private _worldOrigin: Vector3 = new Vector3()
|
||||
public get worldSize() {
|
||||
World.worldBox.getCenter(this._worldOrigin)
|
||||
const size = new Vector3().subVectors(World.worldBox.max, World.worldBox.min)
|
||||
return {
|
||||
x: size.x,
|
||||
y: size.y,
|
||||
z: size.z
|
||||
}
|
||||
}
|
||||
|
||||
public get worldOrigin() {
|
||||
return this._worldOrigin
|
||||
}
|
||||
|
||||
public constructor(
|
||||
container: HTMLElement,
|
||||
params: ViewerParams = DefaultViewerParams
|
||||
|
||||
@@ -67,6 +67,7 @@ export default class ViewerObjectLoader {
|
||||
let total = 0
|
||||
let viewerLoads = 0
|
||||
let firstObjectPromise = null
|
||||
let parsedObjects = [] // Temporary until refactor
|
||||
for await (const obj of this.loader.getObjectIterator()) {
|
||||
if (this.cancel) {
|
||||
this.viewer.emit('load-progress', {
|
||||
@@ -85,7 +86,7 @@ export default class ViewerObjectLoader {
|
||||
async (objectWrapper) => {
|
||||
await this.converter.asyncPause()
|
||||
objectWrapper.meta.__importedUrl = this.objectUrl
|
||||
this.viewer.sceneManager.addObject(objectWrapper)
|
||||
parsedObjects.push(objectWrapper) // Temporary until refactor
|
||||
viewerLoads++
|
||||
}
|
||||
)
|
||||
@@ -103,7 +104,13 @@ export default class ViewerObjectLoader {
|
||||
await firstObjectPromise
|
||||
}
|
||||
|
||||
// Temporary until refactor
|
||||
for (var k = 0; k < parsedObjects.length; k++) {
|
||||
await this.converter.asyncPause()
|
||||
this.viewer.sceneManager.addObject(parsedObjects[k])
|
||||
}
|
||||
await this.viewer.sceneManager.postLoadFunction()
|
||||
this.viewer.emit('load-complete')
|
||||
|
||||
if (viewerLoads === 0) {
|
||||
console.warn(`Viewer: no 3d objects found in object ${this.objectId}`)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Box3 } from 'three'
|
||||
|
||||
export class World {
|
||||
/* This will no longer exist when we have a scene tree */
|
||||
private static readonly boxes: Array<Box3> = new Array<Box3>()
|
||||
public static readonly worldBox: Box3 = new Box3()
|
||||
|
||||
public static expandWorld(box: Box3) {
|
||||
World.boxes.push(box)
|
||||
World.updateWorld()
|
||||
}
|
||||
|
||||
public static reduceWorld(box: Box3) {
|
||||
World.boxes.splice(World.boxes.indexOf(box), 1)
|
||||
World.updateWorld()
|
||||
}
|
||||
|
||||
public static updateWorld() {
|
||||
World.worldBox.makeEmpty()
|
||||
for (var k = 0; k < this.boxes.length; k++) {
|
||||
World.worldBox.union(World.boxes[k])
|
||||
}
|
||||
}
|
||||
|
||||
public static resetWorld() {
|
||||
World.worldBox.makeEmpty()
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,16 @@
|
||||
import {
|
||||
Box3,
|
||||
BoxBufferGeometry,
|
||||
BufferAttribute,
|
||||
BufferGeometry,
|
||||
Float32BufferAttribute,
|
||||
Matrix4,
|
||||
Uint16BufferAttribute,
|
||||
Uint32BufferAttribute
|
||||
Uint32BufferAttribute,
|
||||
Vector3
|
||||
} from 'three'
|
||||
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry.js'
|
||||
import { World } from '../World'
|
||||
|
||||
export const GEOMETRY_LINES_AS_TRIANGLES = true
|
||||
export enum GeometryAttributes {
|
||||
@@ -29,78 +33,138 @@ export interface GeometryData {
|
||||
*/
|
||||
export class Geometry {
|
||||
static makePointGeometry(geometryData: GeometryData): BufferGeometry {
|
||||
return Geometry.makeMeshGeometry(geometryData)
|
||||
const geometry = Geometry.makeMeshGeometry(geometryData)
|
||||
World.expandWorld(geometry.boundingBox)
|
||||
return geometry
|
||||
}
|
||||
static makePointCloudGeometry(geometryData: GeometryData): BufferGeometry {
|
||||
return Geometry.makeMeshGeometry(geometryData)
|
||||
const geometry = Geometry.makeMeshGeometry(geometryData)
|
||||
World.expandWorld(geometry.boundingBox)
|
||||
return geometry
|
||||
}
|
||||
static makeMeshGeometry(geometryData: GeometryData): BufferGeometry {
|
||||
if (geometryData.bakeTransform) {
|
||||
Geometry.transformGeometryData(geometryData, geometryData.bakeTransform)
|
||||
}
|
||||
const buffer = new BufferGeometry()
|
||||
const geometry = new BufferGeometry()
|
||||
|
||||
if (geometryData.attributes.INDEX) {
|
||||
if (
|
||||
geometryData.attributes.POSITION.length >= 65535 ||
|
||||
geometryData.attributes.INDEX.length >= 65535
|
||||
) {
|
||||
buffer.setIndex(new Uint32BufferAttribute(geometryData.attributes.INDEX, 1))
|
||||
geometry.setIndex(new Uint32BufferAttribute(geometryData.attributes.INDEX, 1))
|
||||
} else {
|
||||
buffer.setIndex(new Uint16BufferAttribute(geometryData.attributes.INDEX, 1))
|
||||
geometry.setIndex(new Uint16BufferAttribute(geometryData.attributes.INDEX, 1))
|
||||
}
|
||||
}
|
||||
|
||||
const position_low = new Float32Array(geometryData.attributes.POSITION.length)
|
||||
const position_high = new Float32Array(geometryData.attributes.POSITION.length)
|
||||
if (geometryData.attributes.POSITION) {
|
||||
buffer.setAttribute(
|
||||
for (var k = 0; k < geometryData.attributes.POSITION.length; k++) {
|
||||
const doubleValue = geometryData.attributes.POSITION[k]
|
||||
if (doubleValue >= 0.0) {
|
||||
const doubleHigh = Math.floor(doubleValue / 65536.0) * 65536.0
|
||||
position_high[k] = doubleHigh
|
||||
position_low[k] = doubleValue - doubleHigh
|
||||
} else {
|
||||
const doubleHigh = Math.floor(-doubleValue / 65536.0) * 65536.0
|
||||
position_high[k] = -doubleHigh
|
||||
position_low[k] = doubleValue + doubleHigh
|
||||
}
|
||||
}
|
||||
geometry.setAttribute(
|
||||
'position',
|
||||
new Float32BufferAttribute(geometryData.attributes.POSITION, 3)
|
||||
)
|
||||
}
|
||||
|
||||
if (geometryData.attributes.COLOR) {
|
||||
buffer.setAttribute(
|
||||
geometry.setAttribute(
|
||||
'color',
|
||||
new Float32BufferAttribute(geometryData.attributes.COLOR, 3)
|
||||
)
|
||||
}
|
||||
|
||||
buffer.computeVertexNormals()
|
||||
buffer.computeBoundingSphere()
|
||||
geometry.computeVertexNormals()
|
||||
geometry.computeBoundingSphere()
|
||||
geometry.computeBoundingBox()
|
||||
|
||||
return buffer
|
||||
World.expandWorld(geometry.boundingBox)
|
||||
|
||||
geometry.setAttribute('position_low', new Float32BufferAttribute(position_low, 3))
|
||||
geometry.setAttribute('position_high', new Float32BufferAttribute(position_high, 3))
|
||||
|
||||
return geometry
|
||||
}
|
||||
|
||||
static makeLineGeometry(geometryData: GeometryData) {
|
||||
if (geometryData.bakeTransform) {
|
||||
Geometry.transformGeometryData(geometryData, geometryData.bakeTransform)
|
||||
}
|
||||
let geometry: { boundingBox: Box3 }
|
||||
if (GEOMETRY_LINES_AS_TRIANGLES) {
|
||||
return this.makeLineGeometry_TRIANGLE(geometryData)
|
||||
geometry = this.makeLineGeometry_TRIANGLE(geometryData)
|
||||
} else {
|
||||
return this.makeLineGeometry_LINE(geometryData)
|
||||
geometry = this.makeLineGeometry_LINE(geometryData)
|
||||
}
|
||||
World.expandWorld(geometry.boundingBox)
|
||||
|
||||
return geometry
|
||||
}
|
||||
|
||||
static makeLineGeometry_LINE(geometryData: GeometryData) {
|
||||
const buffer = new BufferGeometry()
|
||||
const geometry = new BufferGeometry()
|
||||
if (geometryData.attributes.POSITION) {
|
||||
buffer.setAttribute(
|
||||
geometry.setAttribute(
|
||||
'position',
|
||||
new Float32BufferAttribute(geometryData.attributes.POSITION, 3)
|
||||
)
|
||||
|
||||
if (geometryData.bakeTransform) {
|
||||
buffer.attributes.position.applyMatrix4(geometryData.bakeTransform)
|
||||
}
|
||||
geometry.computeBoundingBox()
|
||||
const position_low = new Float32Array(geometryData.attributes.POSITION.length)
|
||||
const position_high = new Float32Array(geometryData.attributes.POSITION.length)
|
||||
if (geometryData.attributes.POSITION) {
|
||||
for (var k = 0; k < geometryData.attributes.POSITION.length; k++) {
|
||||
const doubleValue = geometryData.attributes.POSITION[k]
|
||||
if (doubleValue >= 0.0) {
|
||||
const doubleHigh = Math.floor(doubleValue / 65536.0) * 65536.0
|
||||
position_high[k] = doubleHigh
|
||||
position_low[k] = doubleValue - doubleHigh
|
||||
} else {
|
||||
const doubleHigh = Math.floor(-doubleValue / 65536.0) * 65536.0
|
||||
position_high[k] = -doubleHigh
|
||||
position_low[k] = doubleValue + doubleHigh
|
||||
}
|
||||
}
|
||||
}
|
||||
return buffer
|
||||
geometry.setAttribute('position_low', new Float32BufferAttribute(position_low, 3))
|
||||
geometry.setAttribute('position_high', new Float32BufferAttribute(position_high, 3))
|
||||
|
||||
return geometry
|
||||
}
|
||||
|
||||
static makeLineGeometry_TRIANGLE(geometryData: GeometryData) {
|
||||
const geometry = new LineGeometry()
|
||||
geometry.setPositions(geometryData.attributes.POSITION)
|
||||
if (geometryData.attributes.COLOR) geometry.setColors(geometryData.attributes.COLOR)
|
||||
geometry.computeBoundingBox()
|
||||
const position_low = new Float32Array(geometryData.attributes.POSITION.length)
|
||||
const position_high = new Float32Array(geometryData.attributes.POSITION.length)
|
||||
for (var k = 0; k < geometryData.attributes.POSITION.length; k++) {
|
||||
const doubleValue = geometryData.attributes.POSITION[k]
|
||||
if (doubleValue >= 0.0) {
|
||||
const doubleHigh = Math.floor(doubleValue / 65536.0) * 65536.0
|
||||
position_high[k] = doubleHigh
|
||||
position_low[k] = doubleValue - doubleHigh
|
||||
} else {
|
||||
const doubleHigh = Math.floor(-doubleValue / 65536.0) * 65536.0
|
||||
position_high[k] = -doubleHigh
|
||||
position_low[k] = doubleValue + doubleHigh
|
||||
}
|
||||
}
|
||||
geometry.setAttribute('position_low', new Float32BufferAttribute(position_low, 3))
|
||||
geometry.setAttribute('position_high', new Float32BufferAttribute(position_high, 3))
|
||||
return geometry
|
||||
}
|
||||
|
||||
@@ -215,4 +279,37 @@ export class Geometry {
|
||||
}
|
||||
return colors
|
||||
}
|
||||
|
||||
public static DoubleToHighLow(input: Vector3, low: Vector3, high: Vector3) {
|
||||
let doubleValue = input.x
|
||||
if (doubleValue >= 0.0) {
|
||||
const doubleHigh = Math.floor(doubleValue / 65536.0) * 65536.0
|
||||
high.x = doubleHigh
|
||||
low.x = doubleValue - doubleHigh
|
||||
} else {
|
||||
const doubleHigh = Math.floor(-doubleValue / 65536.0) * 65536.0
|
||||
high.x = -doubleHigh
|
||||
low.x = doubleValue + doubleHigh
|
||||
}
|
||||
doubleValue = input.y
|
||||
if (doubleValue >= 0.0) {
|
||||
const doubleHigh = Math.floor(doubleValue / 65536.0) * 65536.0
|
||||
high.y = doubleHigh
|
||||
low.y = doubleValue - doubleHigh
|
||||
} else {
|
||||
const doubleHigh = Math.floor(-doubleValue / 65536.0) * 65536.0
|
||||
high.y = -doubleHigh
|
||||
low.y = doubleValue + doubleHigh
|
||||
}
|
||||
doubleValue = input.z
|
||||
if (doubleValue >= 0.0) {
|
||||
const doubleHigh = Math.floor(doubleValue / 65536.0) * 65536.0
|
||||
high.z = doubleHigh
|
||||
low.z = doubleValue - doubleHigh
|
||||
} else {
|
||||
const doubleHigh = Math.floor(-doubleValue / 65536.0) * 65536.0
|
||||
high.z = -doubleHigh
|
||||
low.z = doubleValue + doubleHigh
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
import { speckle_line_vert } from './shaders/speckle-line-vert'
|
||||
import { speckle_line_frag } from './shaders/speckle-line-frag'
|
||||
import { UniformsUtils, ShaderLib, Vector3, MeshStandardMaterial } from 'three'
|
||||
import { Matrix4 } from 'three'
|
||||
import { Geometry } from '../converter/Geometry'
|
||||
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js'
|
||||
|
||||
class SpeckleLineMaterial extends LineMaterial {
|
||||
private static readonly matBuff: Matrix4 = new Matrix4()
|
||||
|
||||
constructor(parameters, defines = []) {
|
||||
super(parameters)
|
||||
|
||||
this.userData.uViewer_high = {
|
||||
value: new Vector3()
|
||||
}
|
||||
this.userData.uViewer_low = {
|
||||
value: new Vector3()
|
||||
}
|
||||
;(this as any).vertProgram = speckle_line_vert
|
||||
;(this as any).fragProgram = speckle_line_frag
|
||||
;(this as any).uniforms = UniformsUtils.merge([
|
||||
ShaderLib.line.uniforms,
|
||||
{
|
||||
uViewer_high: {
|
||||
value: this.userData.uViewer_high.value
|
||||
},
|
||||
uViewer_low: {
|
||||
value: this.userData.uViewer_low.value
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
this.onBeforeCompile = function (shader) {
|
||||
shader.uniforms.uViewer_high = this.userData.uViewer_high
|
||||
shader.uniforms.uViewer_low = this.userData.uViewer_low
|
||||
shader.vertexShader = this.vertProgram
|
||||
shader.fragmentShader = this.fragProgram
|
||||
}
|
||||
|
||||
for (var k = 0; k < defines.length; k++) {
|
||||
this.defines[defines[k]] = ''
|
||||
}
|
||||
}
|
||||
|
||||
copy(source) {
|
||||
super.copy(source)
|
||||
this.userData = {}
|
||||
this.userData.uViewer_high = {
|
||||
value: new Vector3()
|
||||
}
|
||||
this.userData.uViewer_low = {
|
||||
value: new Vector3()
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
onBeforeRender(_this, scene, camera, geometry, object, group) {
|
||||
SpeckleLineMaterial.matBuff.copy(camera.matrixWorldInverse)
|
||||
SpeckleLineMaterial.matBuff.elements[12] = 0
|
||||
SpeckleLineMaterial.matBuff.elements[13] = 0
|
||||
SpeckleLineMaterial.matBuff.elements[14] = 0
|
||||
SpeckleLineMaterial.matBuff.multiply(object.matrixWorld)
|
||||
object.modelViewMatrix.copy(SpeckleLineMaterial.matBuff)
|
||||
|
||||
let uViewer_low = new Vector3()
|
||||
let uViewer_high = new Vector3()
|
||||
let uViewer = new Vector3(
|
||||
camera.matrixWorld.elements[12],
|
||||
camera.matrixWorld.elements[13],
|
||||
camera.matrixWorld.elements[14]
|
||||
)
|
||||
|
||||
Geometry.DoubleToHighLow(uViewer, uViewer_low, uViewer_high)
|
||||
this.userData.uViewer_high.value.copy(uViewer_high)
|
||||
this.userData.uViewer_low.value.copy(uViewer_low)
|
||||
this.needsUpdate = true
|
||||
}
|
||||
}
|
||||
|
||||
export default SpeckleLineMaterial
|
||||
@@ -0,0 +1,81 @@
|
||||
import { speckle_standard_vert } from './shaders/speckle-standard-vert'
|
||||
import { speckle_standard_frag } from './shaders/speckle-standard-frag'
|
||||
import { UniformsUtils, ShaderLib, Vector3, MeshStandardMaterial } from 'three'
|
||||
import { Matrix4 } from 'three'
|
||||
import { Geometry } from '../converter/Geometry'
|
||||
|
||||
class SpeckleStandardMaterial extends MeshStandardMaterial {
|
||||
private static readonly matBuff: Matrix4 = new Matrix4()
|
||||
constructor(parameters, defines = []) {
|
||||
super(parameters)
|
||||
|
||||
this.userData.uViewer_high = {
|
||||
value: new Vector3()
|
||||
}
|
||||
this.userData.uViewer_low = {
|
||||
value: new Vector3()
|
||||
}
|
||||
;(this as any).vertProgram = speckle_standard_vert
|
||||
;(this as any).fragProgram = speckle_standard_frag
|
||||
;(this as any).uniforms = UniformsUtils.merge([
|
||||
ShaderLib.standard.uniforms,
|
||||
{
|
||||
uViewer_high: {
|
||||
value: this.userData.uViewer_high.value
|
||||
},
|
||||
uViewer_low: {
|
||||
value: this.userData.uViewer_low.value
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
this.onBeforeCompile = function (shader) {
|
||||
shader.uniforms.uViewer_high = this.userData.uViewer_high
|
||||
shader.uniforms.uViewer_low = this.userData.uViewer_low
|
||||
shader.vertexShader = this.vertProgram
|
||||
shader.fragmentShader = this.fragProgram
|
||||
}
|
||||
|
||||
for (var k = 0; k < defines.length; k++) {
|
||||
this.defines[defines[k]] = ''
|
||||
}
|
||||
}
|
||||
|
||||
copy(source) {
|
||||
super.copy(source)
|
||||
this.userData = {}
|
||||
this.userData.uViewer_high = {
|
||||
value: new Vector3()
|
||||
}
|
||||
this.userData.uViewer_low = {
|
||||
value: new Vector3()
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
onBeforeRender(_this, scene, camera, geometry, object, group) {
|
||||
SpeckleStandardMaterial.matBuff.copy(camera.matrixWorldInverse)
|
||||
SpeckleStandardMaterial.matBuff.elements[12] = 0
|
||||
SpeckleStandardMaterial.matBuff.elements[13] = 0
|
||||
SpeckleStandardMaterial.matBuff.elements[14] = 0
|
||||
SpeckleStandardMaterial.matBuff.multiply(object.matrixWorld)
|
||||
object.modelViewMatrix.copy(SpeckleStandardMaterial.matBuff)
|
||||
|
||||
let uViewer_low = new Vector3()
|
||||
let uViewer_high = new Vector3()
|
||||
let uViewer = new Vector3(
|
||||
camera.matrixWorld.elements[12],
|
||||
camera.matrixWorld.elements[13],
|
||||
camera.matrixWorld.elements[14]
|
||||
)
|
||||
|
||||
Geometry.DoubleToHighLow(uViewer, uViewer_low, uViewer_high)
|
||||
object.frustumCulled = false
|
||||
this.userData.uViewer_high.value.copy(uViewer_high)
|
||||
this.userData.uViewer_low.value.copy(uViewer_low)
|
||||
this.needsUpdate = true
|
||||
}
|
||||
}
|
||||
|
||||
export default SpeckleStandardMaterial
|
||||
@@ -0,0 +1,160 @@
|
||||
export const speckle_line_frag = /* glsl */ `
|
||||
uniform vec3 diffuse;
|
||||
uniform float opacity;
|
||||
uniform float linewidth;
|
||||
|
||||
#ifdef USE_DASH
|
||||
|
||||
uniform float dashOffset;
|
||||
uniform float dashSize;
|
||||
uniform float gapSize;
|
||||
|
||||
#endif
|
||||
|
||||
varying float vLineDistance;
|
||||
|
||||
#ifdef WORLD_UNITS
|
||||
|
||||
varying vec4 worldPos;
|
||||
varying vec3 worldStart;
|
||||
varying vec3 worldEnd;
|
||||
|
||||
#ifdef USE_DASH
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
#endif
|
||||
|
||||
#include <common>
|
||||
#include <color_pars_fragment>
|
||||
#include <fog_pars_fragment>
|
||||
#include <logdepthbuf_pars_fragment>
|
||||
#include <clipping_planes_pars_fragment>
|
||||
|
||||
vec2 closestLineToLine(vec3 p1, vec3 p2, vec3 p3, vec3 p4) {
|
||||
|
||||
float mua;
|
||||
float mub;
|
||||
|
||||
vec3 p13 = p1 - p3;
|
||||
vec3 p43 = p4 - p3;
|
||||
|
||||
vec3 p21 = p2 - p1;
|
||||
|
||||
float d1343 = dot( p13, p43 );
|
||||
float d4321 = dot( p43, p21 );
|
||||
float d1321 = dot( p13, p21 );
|
||||
float d4343 = dot( p43, p43 );
|
||||
float d2121 = dot( p21, p21 );
|
||||
|
||||
float denom = d2121 * d4343 - d4321 * d4321;
|
||||
|
||||
float numer = d1343 * d4321 - d1321 * d4343;
|
||||
|
||||
mua = numer / denom;
|
||||
mua = clamp( mua, 0.0, 1.0 );
|
||||
mub = ( d1343 + d4321 * ( mua ) ) / d4343;
|
||||
mub = clamp( mub, 0.0, 1.0 );
|
||||
|
||||
return vec2( mua, mub );
|
||||
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
#include <clipping_planes_fragment>
|
||||
|
||||
#ifdef USE_DASH
|
||||
|
||||
if ( vUv.y < - 1.0 || vUv.y > 1.0 ) discard; // discard endcaps
|
||||
|
||||
if ( mod( vLineDistance + dashOffset, dashSize + gapSize ) > dashSize ) discard; // todo - FIX
|
||||
|
||||
#endif
|
||||
|
||||
float alpha = opacity;
|
||||
|
||||
#ifdef WORLD_UNITS
|
||||
|
||||
// Find the closest points on the view ray and the line segment
|
||||
vec3 rayEnd = normalize( worldPos.xyz ) * 1e5;
|
||||
vec3 lineDir = worldEnd - worldStart;
|
||||
vec2 params = closestLineToLine( worldStart, worldEnd, vec3( 0.0, 0.0, 0.0 ), rayEnd );
|
||||
|
||||
vec3 p1 = worldStart + lineDir * params.x;
|
||||
vec3 p2 = rayEnd * params.y;
|
||||
vec3 delta = p1 - p2;
|
||||
float len = length( delta );
|
||||
float norm = len / linewidth;
|
||||
|
||||
#ifndef USE_DASH
|
||||
|
||||
#ifdef USE_ALPHA_TO_COVERAGE
|
||||
|
||||
float dnorm = fwidth( norm );
|
||||
alpha = 1.0 - smoothstep( 0.5 - dnorm, 0.5 + dnorm, norm );
|
||||
|
||||
#else
|
||||
|
||||
if ( norm > 0.5 ) {
|
||||
|
||||
discard;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifdef USE_ALPHA_TO_COVERAGE
|
||||
|
||||
// artifacts appear on some hardware if a derivative is taken within a conditional
|
||||
float a = vUv.x;
|
||||
float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0;
|
||||
float len2 = a * a + b * b;
|
||||
float dlen = fwidth( len2 );
|
||||
|
||||
if ( abs( vUv.y ) > 1.0 ) {
|
||||
|
||||
alpha = 1.0 - smoothstep( 1.0 - dlen, 1.0 + dlen, len2 );
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if ( abs( vUv.y ) > 1.0 ) {
|
||||
|
||||
float a = vUv.x;
|
||||
float b = ( vUv.y > 0.0 ) ? vUv.y - 1.0 : vUv.y + 1.0;
|
||||
float len2 = a * a + b * b;
|
||||
|
||||
if ( len2 > 1.0 ) discard;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
vec4 diffuseColor = vec4( diffuse, alpha );
|
||||
|
||||
#include <logdepthbuf_fragment>
|
||||
#include <color_fragment>
|
||||
|
||||
gl_FragColor = vec4( diffuseColor.rgb, alpha );
|
||||
|
||||
#include <tonemapping_fragment>
|
||||
#include <encodings_fragment>
|
||||
#include <fog_fragment>
|
||||
#include <premultiplied_alpha_fragment>
|
||||
|
||||
}
|
||||
`
|
||||
@@ -0,0 +1,244 @@
|
||||
export const speckle_line_vert = /* glsl */ `
|
||||
#include <common>
|
||||
#include <color_pars_vertex>
|
||||
#include <fog_pars_vertex>
|
||||
#include <logdepthbuf_pars_vertex>
|
||||
#include <clipping_planes_pars_vertex>
|
||||
|
||||
uniform float linewidth;
|
||||
uniform vec2 resolution;
|
||||
|
||||
uniform vec3 uViewer_high;
|
||||
uniform vec3 uViewer_low;
|
||||
|
||||
attribute vec3 instanceStart;
|
||||
attribute vec3 instanceEnd;
|
||||
|
||||
attribute vec3 instanceColorStart;
|
||||
attribute vec3 instanceColorEnd;
|
||||
|
||||
attribute vec3 position_high;
|
||||
attribute vec3 position_low;
|
||||
|
||||
#ifdef WORLD_UNITS
|
||||
|
||||
varying vec4 worldPos;
|
||||
varying vec3 worldStart;
|
||||
varying vec3 worldEnd;
|
||||
|
||||
#ifdef USE_DASH
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_DASH
|
||||
|
||||
uniform float dashScale;
|
||||
attribute float instanceDistanceStart;
|
||||
attribute float instanceDistanceEnd;
|
||||
varying float vLineDistance;
|
||||
|
||||
#endif
|
||||
|
||||
void trimSegment( const in vec4 start, inout vec4 end ) {
|
||||
|
||||
// trim end segment so it terminates between the camera plane and the near plane
|
||||
|
||||
// conservative estimate of the near plane
|
||||
float a = projectionMatrix[ 2 ][ 2 ]; // 3nd entry in 3th column
|
||||
float b = projectionMatrix[ 3 ][ 2 ]; // 3nd entry in 4th column
|
||||
float nearEstimate = - 0.5 * b / a;
|
||||
|
||||
float alpha = ( nearEstimate - start.z ) / ( end.z - start.z );
|
||||
|
||||
end.xyz = mix( start.xyz, end.xyz, alpha );
|
||||
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 highDifference = vec3(position_high.xyz - uViewer_high);
|
||||
vec3 lowDifference = vec3(position_low.xyz - uViewer_low);
|
||||
vec3 computedPosition = position;//highDifference.xyz + lowDifference.xyz;
|
||||
#ifdef USE_COLOR
|
||||
|
||||
vColor.xyz = ( computedPosition.y < 0.5 ) ? instanceColorStart : instanceColorEnd;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_DASH
|
||||
|
||||
vLineDistance = ( computedPosition.y < 0.5 ) ? dashScale * instanceDistanceStart : dashScale * instanceDistanceEnd;
|
||||
vUv = uv;
|
||||
|
||||
#endif
|
||||
|
||||
float aspect = resolution.x / resolution.y;
|
||||
|
||||
// camera space
|
||||
vec3 startHighDifference = vec3(instanceStart.xyz - uViewer_high);
|
||||
vec3 startLowDifference = vec3(instanceStart.xyz - uViewer_low);
|
||||
vec3 endHighDifference = vec3(instanceEnd.xyz - uViewer_high);
|
||||
vec3 endLowDifference = vec3(instanceEnd.xyz - uViewer_low);
|
||||
vec4 start = modelViewMatrix * vec4( startLowDifference + startHighDifference, 1.0 );
|
||||
vec4 end = modelViewMatrix * vec4( endLowDifference + endHighDifference, 1.0 );
|
||||
|
||||
// vec4 start = modelViewMatrix * vec4( instanceStart, 1.0 );
|
||||
// vec4 end = modelViewMatrix * vec4( instanceEnd, 1.0 );
|
||||
|
||||
#ifdef WORLD_UNITS
|
||||
|
||||
worldStart = start.xyz;
|
||||
worldEnd = end.xyz;
|
||||
|
||||
#else
|
||||
|
||||
vUv = uv;
|
||||
|
||||
#endif
|
||||
|
||||
// special case for perspective projection, and segments that terminate either in, or behind, the camera plane
|
||||
// clearly the gpu firmware has a way of addressing this issue when projecting into ndc space
|
||||
// but we need to perform ndc-space calculations in the shader, so we must address this issue directly
|
||||
// perhaps there is a more elegant solution -- WestLangley
|
||||
|
||||
bool perspective = ( projectionMatrix[ 2 ][ 3 ] == - 1.0 ); // 4th entry in the 3rd column
|
||||
|
||||
if ( perspective ) {
|
||||
|
||||
if ( start.z < 0.0 && end.z >= 0.0 ) {
|
||||
|
||||
trimSegment( start, end );
|
||||
|
||||
} else if ( end.z < 0.0 && start.z >= 0.0 ) {
|
||||
|
||||
trimSegment( end, start );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// clip space
|
||||
vec4 clipStart = projectionMatrix * start;
|
||||
vec4 clipEnd = projectionMatrix * end;
|
||||
|
||||
// ndc space
|
||||
vec3 ndcStart = clipStart.xyz / clipStart.w;
|
||||
vec3 ndcEnd = clipEnd.xyz / clipEnd.w;
|
||||
|
||||
// direction
|
||||
vec2 dir = ndcEnd.xy - ndcStart.xy;
|
||||
|
||||
// account for clip-space aspect ratio
|
||||
dir.x *= aspect;
|
||||
dir = normalize( dir );
|
||||
|
||||
#ifdef WORLD_UNITS
|
||||
|
||||
// get the offset direction as perpendicular to the view vector
|
||||
vec3 worldDir = normalize( end.xyz - start.xyz );
|
||||
vec3 offset;
|
||||
if ( computedPosition.y < 0.5 ) {
|
||||
|
||||
offset = normalize( cross( start.xyz, worldDir ) );
|
||||
|
||||
} else {
|
||||
|
||||
offset = normalize( cross( end.xyz, worldDir ) );
|
||||
|
||||
}
|
||||
|
||||
// sign flip
|
||||
if ( computedPosition.x < 0.0 ) offset *= - 1.0;
|
||||
|
||||
float forwardOffset = dot( worldDir, vec3( 0.0, 0.0, 1.0 ) );
|
||||
|
||||
// don't extend the line if we're rendering dashes because we
|
||||
// won't be rendering the endcaps
|
||||
#ifndef USE_DASH
|
||||
|
||||
// extend the line bounds to encompass endcaps
|
||||
start.xyz += - worldDir * linewidth * 0.5;
|
||||
end.xyz += worldDir * linewidth * 0.5;
|
||||
|
||||
// shift the position of the quad so it hugs the forward edge of the line
|
||||
offset.xy -= dir * forwardOffset;
|
||||
offset.z += 0.5;
|
||||
|
||||
#endif
|
||||
|
||||
// endcaps
|
||||
if ( computedPosition.y > 1.0 || computedPosition.y < 0.0 ) {
|
||||
|
||||
offset.xy += dir * 2.0 * forwardOffset;
|
||||
|
||||
}
|
||||
|
||||
// adjust for linewidth
|
||||
offset *= linewidth * 0.5;
|
||||
|
||||
// set the world position
|
||||
worldPos = ( computedPosition.y < 0.5 ) ? start : end;
|
||||
worldPos.xyz += offset;
|
||||
|
||||
// project the worldpos
|
||||
vec4 clip = projectionMatrix * worldPos;
|
||||
|
||||
// shift the depth of the projected points so the line
|
||||
// segments overlap neatly
|
||||
vec3 clipPose = ( computedPosition.y < 0.5 ) ? ndcStart : ndcEnd;
|
||||
clip.z = clipPose.z * clip.w;
|
||||
|
||||
#else
|
||||
|
||||
vec2 offset = vec2( dir.y, - dir.x );
|
||||
// undo aspect ratio adjustment
|
||||
dir.x /= aspect;
|
||||
offset.x /= aspect;
|
||||
|
||||
// sign flip
|
||||
if ( computedPosition.x < 0.0 ) offset *= - 1.0;
|
||||
|
||||
// endcaps
|
||||
if ( computedPosition.y < 0.0 ) {
|
||||
|
||||
offset += - dir;
|
||||
|
||||
} else if ( computedPosition.y > 1.0 ) {
|
||||
|
||||
offset += dir;
|
||||
|
||||
}
|
||||
|
||||
// adjust for linewidth
|
||||
offset *= linewidth;
|
||||
|
||||
// adjust for clip-space to screen-space conversion // maybe resolution should be based on viewport ...
|
||||
offset /= resolution.y;
|
||||
|
||||
// select end
|
||||
vec4 clip = ( computedPosition.y < 0.5 ) ? clipStart : clipEnd;
|
||||
|
||||
// back to clip space
|
||||
offset *= clip.w;
|
||||
|
||||
clip.xy += offset;
|
||||
|
||||
#endif
|
||||
|
||||
gl_Position = clip;
|
||||
|
||||
vec4 mvPosition = ( computedPosition.y < 0.5 ) ? start : end; // this is an approximation
|
||||
|
||||
#include <logdepthbuf_vertex>
|
||||
#include <clipping_planes_vertex>
|
||||
#include <fog_vertex>
|
||||
|
||||
}
|
||||
`
|
||||
@@ -0,0 +1,147 @@
|
||||
export const speckle_standard_frag = /* glsl */ `
|
||||
#define STANDARD
|
||||
|
||||
#ifdef PHYSICAL
|
||||
#define IOR
|
||||
#define SPECULAR
|
||||
#endif
|
||||
|
||||
uniform vec3 diffuse;
|
||||
uniform vec3 emissive;
|
||||
uniform float roughness;
|
||||
uniform float metalness;
|
||||
uniform float opacity;
|
||||
|
||||
#ifdef IOR
|
||||
uniform float ior;
|
||||
#endif
|
||||
|
||||
#ifdef SPECULAR
|
||||
uniform float specularIntensity;
|
||||
uniform vec3 specularColor;
|
||||
|
||||
#ifdef USE_SPECULARINTENSITYMAP
|
||||
uniform sampler2D specularIntensityMap;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SPECULARCOLORMAP
|
||||
uniform sampler2D specularColorMap;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_CLEARCOAT
|
||||
uniform float clearcoat;
|
||||
uniform float clearcoatRoughness;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SHEEN
|
||||
uniform vec3 sheenColor;
|
||||
uniform float sheenRoughness;
|
||||
|
||||
#ifdef USE_SHEENCOLORMAP
|
||||
uniform sampler2D sheenColorMap;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SHEENROUGHNESSMAP
|
||||
uniform sampler2D sheenRoughnessMap;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
varying vec3 vViewPosition;
|
||||
|
||||
#include <common>
|
||||
#include <packing>
|
||||
#include <dithering_pars_fragment>
|
||||
#include <color_pars_fragment>
|
||||
#include <uv_pars_fragment>
|
||||
#include <uv2_pars_fragment>
|
||||
#include <map_pars_fragment>
|
||||
#include <alphamap_pars_fragment>
|
||||
#include <alphatest_pars_fragment>
|
||||
#include <aomap_pars_fragment>
|
||||
#include <lightmap_pars_fragment>
|
||||
#include <emissivemap_pars_fragment>
|
||||
#include <bsdfs>
|
||||
#include <cube_uv_reflection_fragment>
|
||||
#include <envmap_common_pars_fragment>
|
||||
#include <envmap_physical_pars_fragment>
|
||||
#include <fog_pars_fragment>
|
||||
#include <lights_pars_begin>
|
||||
#include <normal_pars_fragment>
|
||||
#include <lights_physical_pars_fragment>
|
||||
#include <transmission_pars_fragment>
|
||||
#include <shadowmap_pars_fragment>
|
||||
#include <bumpmap_pars_fragment>
|
||||
#include <normalmap_pars_fragment>
|
||||
#include <clearcoat_pars_fragment>
|
||||
#include <roughnessmap_pars_fragment>
|
||||
#include <metalnessmap_pars_fragment>
|
||||
#include <logdepthbuf_pars_fragment>
|
||||
#include <clipping_planes_pars_fragment>
|
||||
|
||||
void main() {
|
||||
|
||||
#include <clipping_planes_fragment>
|
||||
|
||||
vec4 diffuseColor = vec4( diffuse, opacity );
|
||||
ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
|
||||
vec3 totalEmissiveRadiance = emissive;
|
||||
|
||||
#include <logdepthbuf_fragment>
|
||||
#include <map_fragment>
|
||||
#include <color_fragment>
|
||||
#include <alphamap_fragment>
|
||||
#include <alphatest_fragment>
|
||||
#include <roughnessmap_fragment>
|
||||
#include <metalnessmap_fragment>
|
||||
#include <normal_fragment_begin>
|
||||
#include <normal_fragment_maps>
|
||||
#include <clearcoat_normal_fragment_begin>
|
||||
#include <clearcoat_normal_fragment_maps>
|
||||
#include <emissivemap_fragment>
|
||||
|
||||
// accumulation
|
||||
#include <lights_physical_fragment>
|
||||
#include <lights_fragment_begin>
|
||||
#include <lights_fragment_maps>
|
||||
#include <lights_fragment_end>
|
||||
|
||||
// modulation
|
||||
#include <aomap_fragment>
|
||||
|
||||
vec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;
|
||||
vec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;
|
||||
|
||||
#include <transmission_fragment>
|
||||
|
||||
vec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;
|
||||
|
||||
#ifdef USE_SHEEN
|
||||
|
||||
// Sheen energy compensation approximation calculation can be found at the end of
|
||||
// https://drive.google.com/file/d/1T0D1VSyR4AllqIJTQAraEIzjlb5h4FKH/view?usp=sharing
|
||||
float sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );
|
||||
|
||||
outgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_CLEARCOAT
|
||||
|
||||
float dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );
|
||||
|
||||
vec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );
|
||||
|
||||
outgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;
|
||||
|
||||
#endif
|
||||
|
||||
#include <output_fragment>
|
||||
#include <tonemapping_fragment>
|
||||
#include <encodings_fragment>
|
||||
#include <fog_fragment>
|
||||
#include <premultiplied_alpha_fragment>
|
||||
#include <dithering_fragment>
|
||||
|
||||
}
|
||||
`
|
||||
@@ -0,0 +1,77 @@
|
||||
export const speckle_standard_vert = /* glsl */ `
|
||||
#define STANDARD
|
||||
attribute vec3 position_high;
|
||||
attribute vec3 position_low;
|
||||
|
||||
varying vec3 vViewPosition;
|
||||
|
||||
#ifdef USE_TRANSMISSION
|
||||
|
||||
varying vec3 vWorldPosition;
|
||||
|
||||
#endif
|
||||
|
||||
#include <common>
|
||||
#include <uv_pars_vertex>
|
||||
#include <uv2_pars_vertex>
|
||||
#include <displacementmap_pars_vertex>
|
||||
#include <color_pars_vertex>
|
||||
#include <fog_pars_vertex>
|
||||
#include <normal_pars_vertex>
|
||||
#include <morphtarget_pars_vertex>
|
||||
#include <skinning_pars_vertex>
|
||||
#include <shadowmap_pars_vertex>
|
||||
#include <logdepthbuf_pars_vertex>
|
||||
#include <clipping_planes_pars_vertex>
|
||||
|
||||
uniform vec3 uViewer_high;
|
||||
uniform vec3 uViewer_low;
|
||||
|
||||
void main() {
|
||||
|
||||
#include <uv_vertex>
|
||||
#include <uv2_vertex>
|
||||
#include <color_vertex>
|
||||
|
||||
#include <beginnormal_vertex>
|
||||
#include <morphnormal_vertex>
|
||||
#include <skinbase_vertex>
|
||||
#include <skinnormal_vertex>
|
||||
#include <defaultnormal_vertex>
|
||||
#include <normal_vertex>
|
||||
|
||||
#include <begin_vertex>
|
||||
#include <morphtarget_vertex>
|
||||
#include <skinning_vertex>
|
||||
#include <displacementmap_vertex>
|
||||
//#include <project_vertex> // EDITED CHUNK
|
||||
vec3 highDifference = vec3(position_high.xyz - uViewer_high);
|
||||
vec3 lowDifference = vec3(position_low.xyz - uViewer_low);
|
||||
vec4 mvPosition = vec4(highDifference.xyz + lowDifference.xyz , 1.);//vec4( transformed - uViewer, 1.0 );
|
||||
|
||||
#ifdef USE_INSTANCING
|
||||
|
||||
mvPosition = instanceMatrix * mvPosition;
|
||||
|
||||
#endif
|
||||
mvPosition = modelViewMatrix * mvPosition;
|
||||
|
||||
gl_Position = projectionMatrix * mvPosition;
|
||||
|
||||
|
||||
#include <logdepthbuf_vertex>
|
||||
#include <clipping_planes_vertex>
|
||||
|
||||
vViewPosition = - mvPosition.xyz;
|
||||
|
||||
#include <worldpos_vertex>
|
||||
#include <shadowmap_vertex>
|
||||
#include <fog_vertex>
|
||||
|
||||
#ifdef USE_TRANSMISSION
|
||||
|
||||
vWorldPosition = worldPosition.xyz;
|
||||
|
||||
#endif
|
||||
}
|
||||
`
|
||||
Reference in New Issue
Block a user