-
Notifications
You must be signed in to change notification settings - Fork 205
/
transform.js
170 lines (146 loc) · 4.86 KB
/
transform.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
import GL from '@luma.gl/constants';
import {getPassthroughFS} from '@luma.gl/shadertools';
import BufferTransform from './buffer-transform';
import TextureTransform from './texture-transform';
import {isWebGL2, getShaderVersion} from '@luma.gl/webgl';
import {assert, isObjectEmpty} from '../../utils';
import Model from '../model';
// takes source and target buffers/textures and setsup the pipeline
export default class Transform {
static isSupported(gl) {
// TODO : differentiate writting to buffer vs not
return isWebGL2(gl);
}
constructor(gl, props = {}) {
this.gl = gl;
this.model = null;
this.elementCount = 0;
this.bufferTransform = null;
this.textureTransform = null;
this.elementIDBuffer = null;
this._initialize(props);
Object.seal(this);
}
// Delete owned resources.
delete() {
this.model.delete();
/* eslint-disable no-unused-expressions */
this.bufferTransform && this.bufferTransform.delete();
this.textureTransform && this.textureTransform.delete();
/* eslint-enable no-unused-expressions */
}
// Run one transform loop.
run(opts = {}) {
const {clearRenderTarget = true} = opts;
const updatedOpts = this._updateDrawOptions(opts);
if (clearRenderTarget && updatedOpts.framebuffer) {
updatedOpts.framebuffer.clear({color: true});
}
this.model.transform(updatedOpts);
}
// swap resources if a map is provided
swap() {
let swapped = false;
const resourceTransforms = [this.bufferTransform, this.textureTransform].filter(Boolean);
for (const resourceTransform of resourceTransforms) {
swapped = swapped || resourceTransform.swap();
}
assert(swapped, 'Nothing to swap');
}
// Return Buffer object for given varying name.
getBuffer(varyingName = null) {
return this.bufferTransform && this.bufferTransform.getBuffer(varyingName);
}
// Return data either from Buffer or from Texture
getData(opts = {}) {
const resourceTransforms = [this.bufferTransform, this.textureTransform].filter(Boolean);
for (const resourceTransform of resourceTransforms) {
const data = resourceTransform.getData(opts);
if (data) {
return data;
}
}
return null;
}
// Return framebuffer object if rendering to textures
getFramebuffer() {
return this.textureTransform && this.textureTransform.getFramebuffer();
}
// Update some or all buffer/texture bindings.
update(opts = {}) {
if (opts.elementCount) {
this.model.setVertexCount(opts.elementCount);
}
const resourceTransforms = [this.bufferTransform, this.textureTransform].filter(Boolean);
for (const resourceTransform of resourceTransforms) {
resourceTransform.update(opts);
}
}
// Private
_initialize(props = {}) {
const {gl} = this;
this._buildResourceTransforms(gl, props);
props = this._updateModelProps(props);
this.model = new Model(
gl,
Object.assign({}, props, {
fs: props.fs || getPassthroughFS({version: getShaderVersion(props.vs)}),
id: props.id || 'transform-model',
drawMode: props.drawMode || GL.POINTS,
vertexCount: props.elementCount
})
);
/* eslint-disable no-unused-expressions */
this.bufferTransform && this.bufferTransform.setupResources({model: this.model});
/* eslint-enable no-unused-expressions */
}
_updateModelProps(props) {
let updatedProps = Object.assign({}, props);
const resourceTransforms = [this.bufferTransform, this.textureTransform].filter(Boolean);
for (const resourceTransform of resourceTransforms) {
updatedProps = resourceTransform.updateModelProps(updatedProps);
}
return updatedProps;
}
_buildResourceTransforms(gl, props) {
if (canCreateBufferTransform(props)) {
this.bufferTransform = new BufferTransform(gl, props);
}
if (canCreateTextureTransform(props)) {
this.textureTransform = new TextureTransform(gl, props);
}
assert(
this.bufferTransform || this.textureTransform,
'must provide source/feedback buffers or source/target textures'
);
}
_updateDrawOptions(opts) {
let updatedOpts = Object.assign({}, opts);
const resourceTransforms = [this.bufferTransform, this.textureTransform].filter(Boolean);
for (const resourceTransform of resourceTransforms) {
updatedOpts = Object.assign(updatedOpts, resourceTransform.getDrawOptions(updatedOpts));
}
return updatedOpts;
}
}
// Helper Methods
function canCreateBufferTransform(props) {
if (
!isObjectEmpty(props.sourceBuffers) ||
!isObjectEmpty(props.feedbackBuffers) ||
(props.varyings && props.varyings.length > 0)
) {
return true;
}
return false;
}
function canCreateTextureTransform(props) {
if (
!isObjectEmpty(props._sourceTextures) ||
props._targetTexture ||
props._targetTextureVarying
) {
return true;
}
return false;
}