claygl-next
Advanced tools
Comparing version 2.0.0-alpha.10 to 2.0.0-alpha.11
@@ -0,1 +1,2 @@ | ||
import { isTextureUniform } from '../Shader'; | ||
import Texture from '../Texture'; | ||
@@ -41,16 +42,18 @@ const usedMap = new WeakMap(); | ||
const uniformName = textureUniforms[u]; | ||
const val = material.uniforms[uniformName].value; | ||
const uniformType = material.uniforms[uniformName].type; | ||
const uniformObj = material.uniforms[uniformName]; | ||
const val = uniformObj.value; | ||
if (!val) { | ||
continue; | ||
} | ||
if (uniformType === 't') { | ||
updateUsed(val, textureResourceList); | ||
} | ||
else if (uniformType === 'tv') { | ||
for (let k = 0; k < val.length; k++) { | ||
if (val[k]) { | ||
updateUsed(val[k], textureResourceList); | ||
if (isTextureUniform(uniformObj)) { | ||
if (uniformObj.array) { | ||
for (let k = 0; k < val.length; k++) { | ||
if (val[k]) { | ||
updateUsed(val[k], textureResourceList); | ||
} | ||
} | ||
} | ||
else { | ||
updateUsed(val, textureResourceList); | ||
} | ||
} | ||
@@ -57,0 +60,0 @@ } |
@@ -51,3 +51,3 @@ import Renderer from './Renderer'; | ||
interface App3DOpts { | ||
devicePixelRatio?: number; | ||
pixelRatio?: number; | ||
width?: number; | ||
@@ -88,3 +88,2 @@ height?: number; | ||
shader?: T; | ||
textureConvertToPOT?: boolean; | ||
textureFlipY?: boolean; | ||
@@ -246,3 +245,2 @@ textureLoaded?: (textureName: string, texture: Texture) => void; | ||
* @param {boolean} [transparent=false] If material is transparent. | ||
* @param {boolean} [textureConvertToPOT=false] Force convert None Power of Two texture to Power of two so it can be tiled. | ||
* @param {boolean} [textureFlipY=true] If flip y of texture. | ||
@@ -249,0 +247,0 @@ * @param {Function} [textureLoaded] Callback when single texture loaded. |
@@ -38,2 +38,3 @@ // TODO createCompositor | ||
import { EventManager } from './app/EventManager'; | ||
import { isTextureUniform } from './Shader'; | ||
import { createStandardShader } from './shader/create'; | ||
@@ -101,3 +102,3 @@ /** | ||
isDomCanvas && (rendererOpts.canvas = container); | ||
opts.devicePixelRatio && (rendererOpts.devicePixelRatio = opts.devicePixelRatio); | ||
opts.pixelRatio && (rendererOpts.pixelRatio = opts.pixelRatio); | ||
[ | ||
@@ -281,20 +282,13 @@ 'alpha', | ||
const promise = new Promise((resolve, reject) => { | ||
var _a; | ||
const texture = this.loadTextureSync(urlOrImg, opts); | ||
if (!texture.isRenderable()) { | ||
texture.onload(() => { | ||
if (this._disposed) { | ||
return; | ||
} | ||
(_a = texture.checkReady()) === null || _a === void 0 ? void 0 : _a.then(() => { | ||
if (!this._disposed) { | ||
resolve(texture); | ||
}); | ||
texture.onerror(() => { | ||
if (this._disposed) { | ||
return; | ||
} | ||
} | ||
}, () => { | ||
if (!this._disposed) { | ||
reject(); | ||
}); | ||
} | ||
else { | ||
resolve(texture); | ||
} | ||
} | ||
}); | ||
}); | ||
@@ -333,5 +327,2 @@ if (useCache) { | ||
fileType: 'hdr' | ||
}, function () { | ||
texture.dirty(); | ||
texture.trigger('load', texture); | ||
}); | ||
@@ -345,3 +336,3 @@ util.assign(texture, opts); | ||
else if (isImageLikeElement(urlOrImg)) { | ||
texture.image = urlOrImg; | ||
texture.source = urlOrImg; | ||
texture.dynamic = urlOrImg instanceof HTMLVideoElement; | ||
@@ -367,16 +358,3 @@ } | ||
const textureCube = this.loadTextureCubeSync(imgList, opts); | ||
return new Promise(function (resolve, reject) { | ||
if (textureCube.isRenderable()) { | ||
resolve(textureCube); | ||
} | ||
else { | ||
textureCube | ||
.onload(function () { | ||
resolve(textureCube); | ||
}) | ||
.onerror(function () { | ||
reject(); | ||
}); | ||
} | ||
}); | ||
return textureCube.checkReady().then(() => textureCube); | ||
} | ||
@@ -413,3 +391,3 @@ /** | ||
else { | ||
textureCube.image = util.assign({}, imgList); | ||
textureCube.source = util.assign({}, imgList); | ||
} | ||
@@ -424,3 +402,2 @@ return textureCube; | ||
* @param {boolean} [transparent=false] If material is transparent. | ||
* @param {boolean} [textureConvertToPOT=false] Force convert None Power of Two texture to Power of two so it can be tiled. | ||
* @param {boolean} [textureFlipY=true] If flip y of texture. | ||
@@ -451,7 +428,6 @@ * @param {Function} [textureLoaded] Callback when single texture loaded. | ||
if (uniformObj && val != null) { | ||
if ((uniforms[uniformName].type === 't' || isImageLikeElement(val)) && | ||
if ((isTextureUniform(uniformObj) || isImageLikeElement(val)) && | ||
!(val instanceof Texture)) { | ||
// Try to load a texture. | ||
texturesLoading.push(this.loadTexture(val, { | ||
convertToPOT: matConfig.textureConvertToPOT || false, | ||
flipY: util.optional(matConfig.textureFlipY, true) | ||
@@ -789,9 +765,3 @@ }).then(makeTextureSetter(uniformName))); | ||
if (envImage.textureType === 'textureCube') { | ||
loadPromise = envImage.isRenderable() | ||
? Promise.resolve(envImage) | ||
: new Promise(function (resolve) { | ||
envImage.onload(() => { | ||
resolve(envImage); | ||
}); | ||
}); | ||
loadPromise = envImage.checkReady().then(() => envImage); | ||
} | ||
@@ -886,11 +856,3 @@ else { | ||
else { | ||
Promise.all(result.textures.map(function (texture) { | ||
if (texture.isRenderable()) { | ||
return Promise.resolve(texture); | ||
} | ||
return new Promise(function (resolve) { | ||
texture.onload(resolve); | ||
texture.onerror(resolve); | ||
}); | ||
})) | ||
Promise.all(result.textures.map((texture) => texture.checkReady().then(() => texture))) | ||
.then(function () { | ||
@@ -897,0 +859,0 @@ afterLoad(result); |
import { setCanvasSize } from './core/util'; | ||
import Timeline from './Timeline'; | ||
export { default as Renderer } from './Renderer'; | ||
export type { RenderHooks, RenderableObject } from './Renderer'; | ||
export { default as Material } from './Material'; | ||
@@ -18,8 +19,12 @@ export { default as Shader, glsl, createShaderMixin, VertexShader, FragmentShader } from './Shader'; | ||
export { default as Camera } from './Camera'; | ||
export { default as GLRenderer } from './gl/GLRenderer'; | ||
export { default as GLPipeline } from './gl/GLPipeline'; | ||
export { default as StandardMaterial } from './StandardMaterial'; | ||
export { Timeline }; | ||
export { default as Texture } from './Texture'; | ||
export type { TextureImageSource, TexturePixelSource, TextureSource } from './Texture'; | ||
export { default as Texture2D } from './Texture2D'; | ||
export { default as Texture2DArray } from './Texture2DArray'; | ||
export { default as Texture3D } from './Texture3D'; | ||
export { default as TextureCube } from './TextureCube'; | ||
export type { TextureCubeSource } from './TextureCube'; | ||
export declare function startTimeline(onframe?: (deltaTime: number) => void): Timeline; | ||
@@ -50,5 +55,7 @@ export { setCanvasSize }; | ||
export { default as CompositeNode } from './composite/CompositeNode'; | ||
export type { CompositeNodeOutput, CompositeNodeInput } from './composite/CompositeNode'; | ||
export { default as FilterCompositeNode } from './composite/FilterNode'; | ||
export { default as SceneCompositeNode } from './composite/SceneNode'; | ||
export { default as GroupCompositeNode } from './composite/GroupNode'; | ||
export type { GroupOutput, GroupInput } from './composite/GroupNode'; | ||
export { default as DeferredGBuffer } from './deferred/GBuffer'; | ||
@@ -59,1 +66,2 @@ export { default as DeferredRenderer } from './deferred/Renderer'; | ||
export { default as ForceField } from './particle/ForceField'; | ||
export { vec2, vec3, vec4, mat2, mat2d, mat3, mat4, quat } from './glmatrix'; |
@@ -19,3 +19,3 @@ import { setCanvasSize } from './core/util'; | ||
export { default as Camera } from './Camera'; | ||
export { default as GLRenderer } from './gl/GLRenderer'; | ||
export { default as GLPipeline } from './gl/GLPipeline'; | ||
export { default as StandardMaterial } from './StandardMaterial'; | ||
@@ -25,2 +25,4 @@ export { Timeline }; | ||
export { default as Texture2D } from './Texture2D'; | ||
export { default as Texture2DArray } from './Texture2DArray'; | ||
export { default as Texture3D } from './Texture3D'; | ||
export { default as TextureCube } from './TextureCube'; | ||
@@ -85,3 +87,3 @@ export function startTimeline(onframe) { | ||
// Some useful types | ||
// export { RenderHooks, RenderableObject, MaterialObject }; | ||
export { vec2, vec3, vec4, mat2, mat2d, mat3, mat4, quat } from './glmatrix'; | ||
//# sourceMappingURL=claygl.js.map |
@@ -43,2 +43,6 @@ import type Renderer from '../Renderer'; | ||
disabled?: boolean; | ||
/** | ||
* If texture will be persisted. | ||
*/ | ||
persist?: boolean; | ||
} | ||
@@ -63,2 +67,6 @@ /** | ||
/** | ||
* If needs depth buffer when render to texture. | ||
*/ | ||
depthBuffer?: boolean; | ||
/** | ||
* Do preparation logic. | ||
@@ -68,3 +76,9 @@ * For example update inputs and outputs. Update texture size etc | ||
abstract prepare(renderer: Renderer): void; | ||
/** | ||
* beforeRender hook | ||
*/ | ||
beforeRender?: (renderer: Renderer, inputTextures: Record<InputKey, Texture>, outputTextures?: Record<OutputKey, Texture>) => void; | ||
/** | ||
* afterRender hook | ||
*/ | ||
afterRender?: () => void; | ||
@@ -71,0 +85,0 @@ /** |
@@ -11,3 +11,2 @@ import Shader, { FragmentShader } from '../Shader'; | ||
clearDepth?: boolean; | ||
blendWithPrevious?: boolean; | ||
} | ||
@@ -18,3 +17,4 @@ declare class FullscreenQuadPass<T extends FragmentShader = FragmentShader> extends Notifier { | ||
clearDepth?: boolean; | ||
blendWithPrevious?: boolean; | ||
beforeRender?: (gl: WebGL2RenderingContext) => void; | ||
afterRender?: (gl: WebGL2RenderingContext) => void; | ||
constructor(frag: T, opts?: Partial<FullscreenQuadPassOpts>); | ||
@@ -21,0 +21,0 @@ render(renderer: Renderer, frameBuffer?: FrameBuffer): void; |
@@ -22,11 +22,8 @@ import OrthoCamera from '../camera/Orthographic'; | ||
this.clearColor = opts.clearColor || false; | ||
this.blendWithPrevious = opts.blendWithPrevious || false; | ||
this.clearDepth = optional(opts.clearDepth, true); | ||
} | ||
render(renderer, frameBuffer) { | ||
this.trigger('beforerender', this, renderer); | ||
// FIXME Don't clear in each pass in default, let the color overwrite the buffer | ||
// FIXME pixels may be discard | ||
let clearBit = this.clearDepth ? constants.DEPTH_BUFFER_BIT : 0; | ||
const blendWithPrevious = this.blendWithPrevious; | ||
// Blend with previous rendered scene in the final output | ||
@@ -36,5 +33,5 @@ // FIXME Configure blend. | ||
this.renderQuad(renderer, frameBuffer, (gl) => { | ||
var _a; | ||
gl.depthMask(true); | ||
gl[blendWithPrevious ? 'enable' : 'disable'](constants.BLEND); | ||
this.material && (this.material.transparent = blendWithPrevious); | ||
(_a = this.beforeRender) === null || _a === void 0 ? void 0 : _a.call(this, gl); | ||
if (this.clearColor) { | ||
@@ -49,4 +46,6 @@ clearBit = clearBit | constants.COLOR_BUFFER_BIT; | ||
gl.clear(clearBit); | ||
}, (gl) => { | ||
var _a; | ||
(_a = this.afterRender) === null || _a === void 0 ? void 0 : _a.call(this, gl); | ||
}); | ||
this.trigger('afterrender', this, renderer); | ||
} | ||
@@ -53,0 +52,0 @@ /** |
@@ -12,2 +12,6 @@ import TexturePool from '../TexturePool'; | ||
private _frameBuffer; | ||
private _frameBufferWithDepth; | ||
private _width; | ||
private _height; | ||
private _dpr; | ||
addNode(node: RenderGraphNode): void; | ||
@@ -18,5 +22,5 @@ removeNode(node: RenderGraphNode): void; | ||
getTexturePool(): TexturePool; | ||
getFrameBuffer(): FrameBuffer; | ||
getFrameBuffer(needsDepthBuffer: boolean): FrameBuffer; | ||
dispose(renderer: Renderer): void; | ||
} | ||
export default RenderGraph; |
@@ -13,2 +13,6 @@ import TexturePool from '../TexturePool'; | ||
}); | ||
this._frameBufferWithDepth = new FrameBuffer(); | ||
this._width = 0; | ||
this._height = 0; | ||
this._dpr = 0; | ||
} | ||
@@ -32,2 +36,12 @@ addNode(node) { | ||
render(renderer, frameBuffer) { | ||
const width = renderer.getWidth(); | ||
const height = renderer.getHeight(); | ||
const dpr = renderer.getPixelRatio(); | ||
if (this._width !== width || this._height !== height || this._dpr !== dpr) { | ||
this._width = width; | ||
this._height = height; | ||
this._dpr = dpr; | ||
// Clear all the previous allocated textures when size changed. | ||
this._texturePool.clear(renderer); | ||
} | ||
const nodes = this._nodes; | ||
@@ -47,4 +61,4 @@ const outputs = nodes.filter((node) => node.isEndNode()); | ||
} | ||
getFrameBuffer() { | ||
return this._frameBuffer; | ||
getFrameBuffer(needsDepthBuffer) { | ||
return needsDepthBuffer ? this._frameBufferWithDepth : this._frameBuffer; | ||
} | ||
@@ -51,0 +65,0 @@ dispose(renderer) { |
@@ -36,2 +36,3 @@ import type FrameBuffer from '../../FrameBuffer'; | ||
private _outputTextures; | ||
private _persistedTextures; | ||
private _needsKeepPrevFrame; | ||
@@ -38,0 +39,0 @@ private _outputRefCount; |
import { COLOR_ATTACHMENT0 } from '../../core/constants'; | ||
import { assign, isFunction, keys, optional } from '../../core/util'; | ||
import Texture2D from '../../Texture2D'; | ||
class RenderGraphNode { | ||
@@ -30,2 +31,4 @@ constructor(compositeNode, renderGraph) { | ||
this._outputTextures = {}; | ||
// Textures will be persisted | ||
this._persistedTextures = {}; | ||
this._needsKeepPrevFrame = {}; | ||
@@ -66,2 +69,6 @@ this._outputRefCount = {}; | ||
params.height = Math.round(params.height); | ||
// Not generate mipmap by default. It will cause huge performance drop. | ||
if (params.useMipmap == null) { | ||
params.useMipmap = false; | ||
} | ||
textureParams[outputName] = params; | ||
@@ -141,4 +148,8 @@ } | ||
const outputNames = hasOutput ? keys(outputLinks) : []; | ||
const sharedFrameBuffer = hasOutput ? renderGraph.getFrameBuffer() : undefined; | ||
const compositeNode = this._compositeNode; | ||
const sharedFrameBuffer = hasOutput | ||
? renderGraph.getFrameBuffer(compositeNode.depthBuffer || false) | ||
: undefined; | ||
const texturePool = renderGraph.getTexturePool(); | ||
const outputTextures = this._outputTextures; | ||
const inputTextures = {}; | ||
@@ -152,23 +163,29 @@ inputNames.forEach((inputName) => { | ||
}); | ||
// MRT Support in chrome | ||
// https://www.khronos.org/registry/webgl/sdk/tests/conformance/extensions/ext-draw-buffers.html | ||
const outputTextures = hasOutput ? {} : undefined; | ||
const MRTOutputTextures = hasOutput ? {} : undefined; | ||
// Clear before rebind. | ||
sharedFrameBuffer && sharedFrameBuffer.clearTextures(); | ||
outputNames.forEach((outputName) => { | ||
outputNames.forEach((outputName, idx) => { | ||
const outputInfo = compositeNode.outputs[outputName]; | ||
const parameters = this.getTextureParams(outputName, renderer); | ||
// TODO Avoid reading from composite node too much | ||
const outputInfo = this._compositeNode.outputs[outputName]; | ||
const texture = texturePool.allocate(parameters); | ||
const attachment = outputInfo.attachment || COLOR_ATTACHMENT0; | ||
this._outputTextures[outputName] = texture; | ||
const persistedTextures = this._persistedTextures; | ||
let texture; | ||
if (!outputInfo.persist) { | ||
texture = texturePool.allocate(parameters); | ||
} | ||
else { | ||
texture = | ||
persistedTextures[outputName] || (persistedTextures[outputName] = new Texture2D()); | ||
// PENDING | ||
assign(texture, parameters); | ||
} | ||
const attachment = outputInfo.attachment || COLOR_ATTACHMENT0 + idx; | ||
outputTextures[outputName] = texture; | ||
MRTOutputTextures[outputName] = texture; | ||
// FIXME attachment changes in different nodes | ||
sharedFrameBuffer.attach(texture, +attachment); | ||
}); | ||
const compositeNode = this._compositeNode; | ||
// TODO. Getting viewport in the beforeRender hook will be wrong because frame buffer is not bound yet. | ||
compositeNode.beforeRender && | ||
compositeNode.beforeRender(renderer, inputTextures, outputTextures); | ||
compositeNode.render(renderer, inputTextures, outputTextures, sharedFrameBuffer || finalFrameBuffer); | ||
compositeNode.beforeRender(renderer, inputTextures, MRTOutputTextures); | ||
compositeNode.render(renderer, inputTextures, MRTOutputTextures, sharedFrameBuffer || finalFrameBuffer); | ||
compositeNode.afterRender && compositeNode.afterRender(); | ||
@@ -181,4 +198,5 @@ inputNames.forEach((inputName) => { | ||
outputNames.forEach((outputName) => { | ||
const texture = outputTextures[outputName]; | ||
if (!outputLinks[outputName].length) { | ||
const texture = MRTOutputTextures[outputName]; | ||
const outputInfo = compositeNode.outputs[outputName]; | ||
if (!outputLinks[outputName].length && !outputInfo.persist) { | ||
texturePool.release(texture); | ||
@@ -238,6 +256,7 @@ } | ||
const outputTexture = this._outputTextures[outputName]; | ||
const outputInfo = this._compositeNode.outputs[outputName]; | ||
if (this._needsKeepPrevFrame[outputName]) { | ||
this._prevOutputTextures[outputName] = outputTexture; | ||
} | ||
else { | ||
else if (!outputInfo.persist) { | ||
texturePool.release(outputTexture); | ||
@@ -253,3 +272,4 @@ } | ||
if (refCount[outputName] <= 0) { | ||
if (link.prevFrame || !this._needsKeepPrevFrame[outputName]) { | ||
const outputInfo = this._compositeNode.outputs[outputName]; | ||
if (!outputInfo.persist && (link.prevFrame || !this._needsKeepPrevFrame[outputName])) { | ||
texturePool.release(texture); | ||
@@ -262,6 +282,3 @@ } | ||
const output = this._compositeNode.outputs[outputName]; | ||
if (output.groupOutput) { | ||
return output.groupOutput; | ||
} | ||
return output; | ||
return output.groupOutput || output; | ||
} | ||
@@ -268,0 +285,0 @@ } |
@@ -13,2 +13,3 @@ import CompositeNode, { CompositeNodeOutput } from './CompositeNode'; | ||
preZ: boolean; | ||
depthBuffer: boolean; | ||
constructor(scene: Scene, camera: Camera, outputs?: Record<OutputKey, CompositeNodeOutput>); | ||
@@ -15,0 +16,0 @@ prepare(): void; |
@@ -8,2 +8,3 @@ import CompositeNode from './CompositeNode'; | ||
this.preZ = false; | ||
this.depthBuffer = true; | ||
this.scene = scene; | ||
@@ -10,0 +11,0 @@ this.camera = camera; |
@@ -51,4 +51,2 @@ // TODO dispose unused textures. | ||
const defaultParams = { | ||
width: 512, | ||
height: 512, | ||
type: constants.UNSIGNED_BYTE, | ||
@@ -58,6 +56,5 @@ format: constants.RGBA, | ||
wrapT: constants.CLAMP_TO_EDGE, | ||
minFilter: constants.LINEAR, | ||
minFilter: constants.LINEAR_MIPMAP_LINEAR, | ||
magFilter: constants.LINEAR, | ||
// Not generate mipmap by default. It will cause huge performance drop. | ||
useMipmap: false, | ||
useMipmap: true, | ||
anisotropic: 1 | ||
@@ -64,0 +61,0 @@ }; |
@@ -62,1 +62,2 @@ /** | ||
export declare const isArray: (arg: any) => arg is any[]; | ||
export declare function assert(cond: boolean, msg?: string): void; |
@@ -159,2 +159,7 @@ let guid = 0; | ||
export const isArray = Array.isArray; | ||
export function assert(cond, msg) { | ||
if (!cond) { | ||
throw new Error(msg); | ||
} | ||
} | ||
//# sourceMappingURL=util.js.map |
@@ -8,2 +8,3 @@ import { get } from './request'; | ||
createImage: () => HTMLImageElement; | ||
loadImage: (src: string, crossOrigin?: string, onload?: () => void, onerror?: (e: any) => void) => HTMLImageElement; | ||
request: { | ||
@@ -10,0 +11,0 @@ get: typeof get; |
@@ -44,2 +44,16 @@ import { get } from './request'; | ||
}; | ||
vendor.loadImage = function (src, crossOrigin, onload, onerror) { | ||
const image = vendor.createImage(); | ||
if (crossOrigin) { | ||
image.crossOrigin = crossOrigin; | ||
} | ||
image.onload = function () { | ||
onload && onload(); | ||
}; | ||
image.onerror = function (e) { | ||
onerror && onerror(e); | ||
}; | ||
image.src = src; | ||
return image; | ||
}; | ||
vendor.request = { | ||
@@ -46,0 +60,0 @@ get |
@@ -12,2 +12,3 @@ import Texture2D from '../Texture2D'; | ||
import { gBuffer1Fragment, gBuffer2Fragment, gBuffer3Fragment, gBufferDebugFragment, gBufferVertex } from '../shader/source/deferred/gbuffer.glsl'; | ||
import { isPixelSource } from '../Texture'; | ||
const renderableGBufferData = new WeakMap(); | ||
@@ -140,12 +141,12 @@ function createFillCanvas(color) { | ||
this._defaultNormalMap = new Texture2D({ | ||
image: createFillCanvas('#000') | ||
source: createFillCanvas('#000') | ||
}); | ||
this._defaultRoughnessMap = new Texture2D({ | ||
image: createFillCanvas('#fff') | ||
source: createFillCanvas('#fff') | ||
}); | ||
this._defaultMetalnessMap = new Texture2D({ | ||
image: createFillCanvas('#fff') | ||
source: createFillCanvas('#fff') | ||
}); | ||
this._defaultDiffuseMap = new Texture2D({ | ||
image: createFillCanvas('#fff') | ||
source: createFillCanvas('#fff') | ||
}); | ||
@@ -210,3 +211,3 @@ this._frameBuffer = new FrameBuffer(); | ||
height: height, | ||
devicePixelRatio: dpr || 1 | ||
pixelRatio: dpr || 1 | ||
}; | ||
@@ -226,3 +227,3 @@ } | ||
height: this._gBufferTex1.height, | ||
devicePixelRatio: 1 | ||
pixelRatio: 1 | ||
}; | ||
@@ -278,3 +279,3 @@ } | ||
if (viewport) { | ||
const dpr = viewport.devicePixelRatio; | ||
const dpr = viewport.pixelRatio; | ||
// use scissor to make sure only clear the viewport | ||
@@ -365,9 +366,14 @@ gl.enable(gl.SCISSOR_TEST); | ||
} | ||
if (!prevSkinMatricesTexture.pixels || | ||
prevSkinMatricesTexture.pixels.length !== skinMatricesTexture.pixels.length) { | ||
prevSkinMatricesTexture.pixels = new Float32Array(skinMatricesTexture.pixels); | ||
const source = skinMatricesTexture.source; | ||
if (!isPixelSource(prevSkinMatricesTexture.source) || | ||
prevSkinMatricesTexture.source.data.length !== source.data.length) { | ||
prevSkinMatricesTexture.source = { | ||
data: new Float32Array(source.data), | ||
width: source.width, | ||
height: source.height | ||
}; | ||
} | ||
else { | ||
for (let i = 0; i < skinMatricesTexture.pixels.length; i++) { | ||
prevSkinMatricesTexture.pixels[i] = skinMatricesTexture.pixels[i]; | ||
for (let i = 0; i < source.data.length; i++) { | ||
prevSkinMatricesTexture.source.data[i] = source.data[i]; | ||
} | ||
@@ -374,0 +380,0 @@ } |
@@ -50,5 +50,3 @@ // Light-pre pass deferred rendering | ||
// TODO Support dynamic material? | ||
this._fullQuadPass = new FullscreenQuadPass(outputFragment, { | ||
blendWithPrevious: true | ||
}); | ||
this._fullQuadPass = new FullscreenQuadPass(outputFragment); | ||
this._depthWriteMat = new Material(new Shader(fullscreenQuadPassVertex, depthWriteFragment)); | ||
@@ -118,3 +116,3 @@ this._lightSphereGeo = new SphereGeo({ | ||
const lightAccumTex = opts.targetTexture || this._lightAccumTex; | ||
const dpr = renderer.getDevicePixelRatio(); | ||
const dpr = renderer.getPixelRatio(); | ||
const isInputGBuffer = opts.gBufferTexture1 && opts.gBufferTexture2 && opts.gBufferTexture3; | ||
@@ -227,3 +225,3 @@ if (this.autoResize && | ||
if (viewport) { | ||
const dpr = viewport.devicePixelRatio; | ||
const dpr = viewport.pixelRatio; | ||
// use scissor to make sure only clear the viewport | ||
@@ -230,0 +228,0 @@ gl.enable(gl.SCISSOR_TEST); |
@@ -14,4 +14,6 @@ import Texture from './Texture'; | ||
viewport?: RendererViewport; | ||
autoGenerateMipmap?: boolean; | ||
private _width; | ||
private _height; | ||
mipmapLevel: number; | ||
private _textures; | ||
@@ -23,3 +25,3 @@ constructor(opts?: Partial<FrameBufferOpts>); | ||
getTextures(): Record<string, { | ||
texture: Texture; | ||
texture: Texture<unknown>; | ||
target: number; | ||
@@ -26,0 +28,0 @@ }>; |
import * as constants from './core/constants'; | ||
import { assert } from './core/util'; | ||
class FrameBuffer { | ||
constructor(opts) { | ||
// Auto generate mipmap after render | ||
// TODO It's some workaround for the case like cubemap prefiltering. | ||
// Which don't need to generate mipmap again. | ||
this.autoGenerateMipmap = true; | ||
this._width = 0; | ||
this._height = 0; | ||
this.mipmapLevel = 0; | ||
this._textures = {}; | ||
this.depthBuffer = true; | ||
const { depthBuffer } = opts || {}; | ||
this.depthBuffer = depthBuffer == null ? true : depthBuffer; | ||
} | ||
@@ -31,8 +38,11 @@ /** | ||
getViewport() { | ||
return (this.viewport || { | ||
const scale = Math.pow(2, this.mipmapLevel); | ||
return ( | ||
// PENDING this.viewport scale mipmapLevel? | ||
this.viewport || { | ||
x: 0, | ||
y: 0, | ||
width: this._width, | ||
height: this._height, | ||
devicePixelRatio: 1 | ||
width: this._width / scale, | ||
height: this._height / scale, | ||
pixelRatio: 1 | ||
}); | ||
@@ -51,5 +61,3 @@ } | ||
attach(texture, attachment, target) { | ||
if (!texture.width) { | ||
throw new Error('The texture attached to color buffer is not a valid.'); | ||
} | ||
assert(texture.width > 0, 'Invalid texture'); | ||
// If the depth_texture extension is enabled, developers | ||
@@ -56,0 +64,0 @@ // Can attach a depth texture to the depth buffer |
@@ -9,3 +9,3 @@ import Ray from './math/Ray'; | ||
import { AttributeSemantic } from './Shader'; | ||
export declare type AttributeType = 'byte' | 'ubyte' | 'short' | 'ushort' | 'float'; | ||
export declare type AttributeType = 'byte' | 'ubyte' | 'short' | 'ushort' | 'float' | 'int'; | ||
export declare type AttributeSize = 1 | 2 | 3 | 4; | ||
@@ -12,0 +12,0 @@ export declare type AttributeValue = { |
@@ -8,2 +8,3 @@ import { genGUID, keys } from './core/util'; | ||
ushort: Uint16Array, | ||
int: Uint32Array, | ||
float: Float32Array | ||
@@ -10,0 +11,0 @@ }[type] || Float32Array); |
@@ -6,2 +6,3 @@ import GeometryBase, { AttributeSize, AttributeType } from '../GeometryBase'; | ||
float: number; | ||
int: number; | ||
byte: number; | ||
@@ -8,0 +9,0 @@ ubyte: number; |
@@ -5,2 +5,3 @@ import * as constants from '../core/constants'; | ||
float: constants.FLOAT, | ||
int: constants.INT, | ||
byte: constants.BYTE, | ||
@@ -126,3 +127,8 @@ ubyte: constants.UNSIGNED_BYTE, | ||
gl.bindBuffer(constants.ARRAY_BUFFER, buffer); | ||
gl.vertexAttribPointer(location, size, glType, false, 0, 0); | ||
if (glType === constants.INT) { | ||
gl.vertexAttribIPointer(location, size, glType, 0, 0); | ||
} | ||
else { | ||
gl.vertexAttribPointer(location, size, glType, false, 0, 0); | ||
} | ||
currentEnabledAttributes[location] = 1; | ||
@@ -129,0 +135,0 @@ if (!lastEnabledAttributes[location]) { |
@@ -5,3 +5,3 @@ import { COLOR_ATTACHMENT0, DEPTH_ATTACHMENT, DEPTH_STENCIL_ATTACHMENT, FRAMEBUFFER, RENDERBUFFER } from '../core/constants'; | ||
constructor(frambuffer) { | ||
// Attached textures, [texture, target, width, height] | ||
// Attached textures, [texture, target, width, height, level] | ||
this._textures = {}; | ||
@@ -13,2 +13,3 @@ this._fb = frambuffer; | ||
const webglFb = this._webglFb || (this._webglFb = gl.createFramebuffer()); | ||
const level = frameBuffer.mipmapLevel; | ||
let webglRenderBuffer = this._webglRb; | ||
@@ -26,3 +27,3 @@ // PENDING. not bind multiple times? if render twice? | ||
// Detach a texture from framebuffer | ||
gl.framebufferTexture2D(FRAMEBUFFER, +attachment, attachedTextures[attachment][1], null, 0); | ||
gl.framebufferTexture2D(FRAMEBUFFER, +attachment, attachedTextures[attachment][1], null, attachedTextures[attachment][4]); | ||
delete attachedTextures[attachment]; | ||
@@ -38,3 +39,2 @@ } | ||
// https://www.khronos.org/registry/webgl/sdk/tests/conformance/extensions/ext-draw-buffers.html | ||
const ext = helpers.getGLExtension('EXT_draw_buffers'); | ||
keys(texturesToAttach).forEach((attachmentStr) => { | ||
@@ -44,2 +44,3 @@ const attachment = +attachmentStr; | ||
const glTexture = helpers.getGLTexture(texture); | ||
// TODO mipmap level not support used with render storage. | ||
width = texture.width; | ||
@@ -56,3 +57,3 @@ height = texture.height; | ||
} | ||
if (ext && attachment >= COLOR_ATTACHMENT0 && attachment <= COLOR_ATTACHMENT0 + 8) { | ||
if (attachment >= COLOR_ATTACHMENT0 && attachment <= COLOR_ATTACHMENT0 + 8) { | ||
bufs.push(attachment); | ||
@@ -65,7 +66,8 @@ } | ||
attached[2] === width && | ||
attached[3] === height) { | ||
attached[3] === height && | ||
attached[4] === level) { | ||
return; | ||
} | ||
gl.framebufferTexture2D(FRAMEBUFFER, attachment, target, glTexture.getWebGLTexture(gl), 0); | ||
attachedTextures[attachment] = [glTexture, target, width, height]; | ||
gl.framebufferTexture2D(FRAMEBUFFER, attachment, target, glTexture.getWebGLTexture(gl), level || 0); | ||
attachedTextures[attachment] = [glTexture, target, width, height, level]; | ||
}); | ||
@@ -98,5 +100,3 @@ if (width && height && !depthAttached && frameBuffer.depthBuffer) { | ||
} | ||
if (ext) { | ||
ext.drawBuffersEXT(bufs); | ||
} | ||
gl.drawBuffers(bufs); | ||
// 0x8CD5, 36053, FRAMEBUFFER_COMPLETE | ||
@@ -125,3 +125,5 @@ // 0x8CD6, 36054, FRAMEBUFFER_INCOMPLETE_ATTACHMENT | ||
// Here update the mipmaps of texture each time after rendered; | ||
this.updateMipmap(gl); | ||
if (this._fb.autoGenerateMipmap) { | ||
this.updateMipmap(gl); | ||
} | ||
} | ||
@@ -128,0 +130,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import Shader, { AttributeSemantic } from '../Shader'; | ||
import Shader, { AttributeSemantic, UniformType } from '../Shader'; | ||
import GLTexture from './GLTexture'; | ||
@@ -23,3 +23,3 @@ declare class GLProgram { | ||
takeTextureSlot(gl: WebGL2RenderingContext, texture?: GLTexture): number; | ||
set(_gl: WebGL2RenderingContext, type: string, symbol: string, value: any, force?: boolean): boolean; | ||
set(_gl: WebGL2RenderingContext, type: UniformType, symbol: string, value: any, valueArray: boolean, force?: boolean): boolean; | ||
setSemanticUniform(_gl: WebGL2RenderingContext, semantic: string, val: any): boolean; | ||
@@ -26,0 +26,0 @@ getAttributeLocation(gl: WebGL2RenderingContext, attribBuffer: { |
@@ -65,3 +65,3 @@ import { assign, genGUID, isArray, keys } from '../core/util'; | ||
} | ||
set(_gl, type, symbol, value, force) { | ||
set(_gl, type, symbol, value, valueArray, force) { | ||
const locationMap = this._uniformLocations; | ||
@@ -82,86 +82,70 @@ const location = locationMap[symbol]; | ||
switch (type) { | ||
case 'm4': | ||
if (!(value instanceof Float32Array)) { | ||
// Use Float32Array is much faster than array when uniformMatrix4fv. | ||
for (let i = 0; i < value.length; i++) { | ||
tmpFloat32Array16[i] = value[i]; | ||
case 'mat4': | ||
if (valueArray) { | ||
if (isArray(value) && isArray(value[0])) { | ||
const tmpArray = new Float32Array(value.length * 16); | ||
let cursor = 0; | ||
for (let i = 0; i < value.length; i++) { | ||
const item = value[i]; | ||
for (let j = 0; j < 16; j++) { | ||
tmpArray[cursor++] = item[j]; | ||
} | ||
} | ||
value = tmpArray; | ||
} | ||
value = tmpFloat32Array16; | ||
// else ArrayBufferView | ||
} | ||
else { | ||
if (!(value instanceof Float32Array)) { | ||
// Use Float32Array is much faster than array when uniformMatrix4fv. | ||
for (let i = 0; i < value.length; i++) { | ||
tmpFloat32Array16[i] = value[i]; | ||
} | ||
value = tmpFloat32Array16; | ||
} | ||
} | ||
_gl.uniformMatrix4fv(location, false, value); | ||
break; | ||
case '2i': | ||
_gl.uniform2i(location, value[0], value[1]); | ||
case 'float': | ||
valueArray ? _gl.uniform1fv(location, value) : _gl.uniform1f(location, value); | ||
break; | ||
case '2f': | ||
_gl.uniform2f(location, value[0], value[1]); | ||
case 'vec2': | ||
valueArray ? _gl.uniform2fv(location, value) : _gl.uniform2f(location, value[0], value[1]); | ||
break; | ||
case '3i': | ||
_gl.uniform3i(location, value[0], value[1], value[2]); | ||
case 'vec3': | ||
valueArray | ||
? _gl.uniform3fv(location, value) | ||
: _gl.uniform3f(location, value[0], value[1], value[2]); | ||
break; | ||
case '3f': | ||
_gl.uniform3f(location, value[0], value[1], value[2]); | ||
case 'vec4': | ||
valueArray | ||
? _gl.uniform4fv(location, value) | ||
: _gl.uniform4f(location, value[0], value[1], value[2], value[3]); | ||
break; | ||
case '4i': | ||
_gl.uniform4i(location, value[0], value[1], value[2], value[3]); | ||
case 'int': | ||
case 'bool': | ||
valueArray ? _gl.uniform1iv(location, value) : _gl.uniform1i(location, value); | ||
break; | ||
case '4f': | ||
_gl.uniform4f(location, value[0], value[1], value[2], value[3]); | ||
case 'ivec2': | ||
valueArray ? _gl.uniform2iv(location, value) : _gl.uniform2i(location, value[0], value[1]); | ||
break; | ||
case '1i': | ||
_gl.uniform1i(location, value); | ||
case 'ivec3': | ||
valueArray | ||
? _gl.uniform3iv(location, value) | ||
: _gl.uniform3i(location, value[0], value[1], value[2]); | ||
break; | ||
case '1f': | ||
_gl.uniform1f(location, value); | ||
case 'ivec4': | ||
valueArray | ||
? _gl.uniform4iv(location, value) | ||
: _gl.uniform4i(location, value[0], value[1], value[2], value[3]); | ||
break; | ||
case '1fv': | ||
_gl.uniform1fv(location, value); | ||
break; | ||
case '1iv': | ||
_gl.uniform1iv(location, value); | ||
break; | ||
case '2iv': | ||
_gl.uniform2iv(location, value); | ||
break; | ||
case '2fv': | ||
_gl.uniform2fv(location, value); | ||
break; | ||
case '3iv': | ||
_gl.uniform3iv(location, value); | ||
break; | ||
case '3fv': | ||
_gl.uniform3fv(location, value); | ||
break; | ||
case '4iv': | ||
_gl.uniform4iv(location, value); | ||
break; | ||
case '4fv': | ||
_gl.uniform4fv(location, value); | ||
break; | ||
case 'm2': | ||
case 'm2v': | ||
case 'mat2': | ||
_gl.uniformMatrix2fv(location, false, value); | ||
break; | ||
case 'm3': | ||
case 'm3v': | ||
case 'mat3': | ||
_gl.uniformMatrix3fv(location, false, value); | ||
break; | ||
case 'm4v': | ||
// Raw value | ||
if (isArray(value) && isArray(value[0])) { | ||
const array = new Float32Array(value.length * 16); | ||
let cursor = 0; | ||
for (let i = 0; i < value.length; i++) { | ||
const item = value[i]; | ||
for (let j = 0; j < 16; j++) { | ||
array[cursor++] = item[j]; | ||
} | ||
} | ||
_gl.uniformMatrix4fv(location, false, array); | ||
} | ||
else { | ||
// ArrayBufferView | ||
_gl.uniformMatrix4fv(location, false, value); | ||
} | ||
break; | ||
// case '_struct': | ||
default: | ||
throw 'Unknown type ' + type; | ||
} | ||
@@ -173,4 +157,5 @@ return true; | ||
if (semanticInfo) { | ||
// Uniform with semantic can't be array. | ||
// Force set for semantic uniforms. | ||
return this.set(_gl, semanticInfo.type, semanticInfo.name, val, true); | ||
return this.set(_gl, semanticInfo.type, semanticInfo.name, val, false, true); | ||
} | ||
@@ -177,0 +162,0 @@ return false; |
import Texture2D from '../Texture2D'; | ||
import Texture2DArray from '../Texture2DArray'; | ||
import Texture3D from '../Texture3D'; | ||
import TextureCube from '../TextureCube'; | ||
import GLExtension from './GLExtension'; | ||
declare type AllTextureType = Texture2D | TextureCube | Texture2DArray | Texture3D; | ||
declare class GLTexture { | ||
@@ -14,3 +17,3 @@ /** | ||
private _webglIns?; | ||
constructor(texture: Texture2D | TextureCube); | ||
constructor(texture: AllTextureType); | ||
bind(gl: WebGL2RenderingContext): void; | ||
@@ -20,4 +23,6 @@ unbind(gl: WebGL2RenderingContext): void; | ||
update(gl: WebGL2RenderingContext, glExt: GLExtension): void; | ||
private _updateTextureData2D; | ||
private _updateTextureDataCube; | ||
private _update_texture2D; | ||
private _update_texture2DArray; | ||
private _update_texture3D; | ||
private _update_textureCube; | ||
private _getBindTarget; | ||
@@ -24,0 +29,0 @@ generateMipmap(gl: WebGL2RenderingContext): void; |
import * as constants from '../core/constants'; | ||
import { getPossiblelInternalFormat } from '../Texture'; | ||
import { isPixelSource } from '../Texture'; | ||
import { cubeTargets } from '../TextureCube'; | ||
const textureTargetMap = { | ||
texture2D: constants.TEXTURE_2D, | ||
textureCube: constants.TEXTURE_CUBE_MAP, | ||
texture2DArray: constants.TEXTURE_2D_ARRAY, | ||
texture3D: constants.TEXTURE_3D | ||
}; | ||
function getAvailableMinFilter(texture) { | ||
@@ -36,4 +42,3 @@ const minFilter = texture.minFilter; | ||
const texture = this._texture; | ||
const isTexture2D = texture.textureType === 'texture2D'; | ||
const textureTarget = isTexture2D ? constants.TEXTURE_2D : constants.TEXTURE_CUBE_MAP; | ||
const textureTarget = textureTargetMap[texture.textureType]; | ||
this.bind(gl); | ||
@@ -46,3 +51,3 @@ // Pixel storage | ||
const glFormat = texture.format; | ||
const glInternalFormat = texture.internalFormat || getPossiblelInternalFormat(texture.format, texture.type); | ||
const glInternalFormat = texture.internalFormat; | ||
const mipmaps = texture.mipmaps || []; | ||
@@ -62,9 +67,4 @@ const mipmapsLen = mipmaps.length; | ||
} | ||
const updateTextureData = (gl, data, level, width, height) => { | ||
if (isTexture2D) { | ||
this._updateTextureData2D(gl, data, level, width, height, glInternalFormat, glFormat, glType); | ||
} | ||
else { | ||
this._updateTextureDataCube(gl, data, level, width, height, glInternalFormat, glFormat, glType); | ||
} | ||
const updateTextureData = (gl, source, level, width, height) => { | ||
this[`_update_${texture.textureType}`](gl, source, level, width, height, texture.depth || 0, glInternalFormat, glFormat, glType); | ||
}; | ||
@@ -80,3 +80,4 @@ if (mipmapsLen) { | ||
else { | ||
updateTextureData(gl, texture, 0, width, height); | ||
updateTextureData(gl, texture.source, 0, width, height); | ||
// TODO check minFilter | ||
if (useMipmap) { | ||
@@ -88,7 +89,4 @@ gl.generateMipmap(textureTarget); | ||
} | ||
_updateTextureData2D(gl, data, level, width, height, glInternalFormat, glFormat, glType) { | ||
if (data.image) { | ||
gl.texImage2D(constants.TEXTURE_2D, level, glInternalFormat, glFormat, glType, data.image); | ||
} | ||
else { | ||
_update_texture2D(gl, source, level, width, height, depth, glInternalFormat, glFormat, glType) { | ||
if (isPixelSource(source) || !source) { | ||
// Can be used as a blank texture when writing render to texture(RTT) | ||
@@ -108,4 +106,4 @@ if ( | ||
glFormat === constants.COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL) { | ||
if (data.pixels) { | ||
gl.compressedTexImage2D(constants.TEXTURE_2D, level, glFormat, width, height, 0, data.pixels); | ||
if (source && source.data) { | ||
gl.compressedTexImage2D(constants.TEXTURE_2D, level, glFormat, width, height, 0, source.data); | ||
} | ||
@@ -116,18 +114,35 @@ else { | ||
} | ||
else { | ||
// Is a render target if pixels is null | ||
gl.texImage2D(constants.TEXTURE_2D, level, glInternalFormat, width, height, 0, glFormat, glType, data.pixels || null); | ||
} | ||
// TODO use texStorage2D if source is undefined. | ||
gl.texImage2D(constants.TEXTURE_2D, level, glInternalFormat, width, height, 0, glFormat, glType, (source && source.data) || null); | ||
} | ||
else { | ||
// Try as image source. | ||
// TODO check? | ||
gl.texImage2D(constants.TEXTURE_2D, level, glInternalFormat, glFormat, glType, source); | ||
} | ||
} | ||
_updateTextureDataCube(_gl, data, level, width, height, glInternalFormat, glFormat, glType) { | ||
_update_texture2DArray(_gl, source, level, width, height, depth, glInternalFormat, glFormat, glType) { | ||
// TODO mipmap | ||
// TODO render target | ||
if (source) { | ||
// TODO | ||
_gl.texStorage3D(constants.TEXTURE_2D_ARRAY, 1, glInternalFormat, width, height, source.length); | ||
source.forEach((sourceSlice, idx) => | ||
// TODO check image size are equal | ||
_gl.texSubImage3D(constants.TEXTURE_2D_ARRAY, 0, 0, 0, idx, width, height, 1, glFormat, glType, (isPixelSource(sourceSlice) ? sourceSlice.data : sourceSlice))); | ||
} | ||
} | ||
_update_texture3D(_gl, source, level, width, height, depth, glInternalFormat, glFormat, glType) { | ||
_gl.texImage3D(constants.TEXTURE_3D, level, glInternalFormat, width, height, depth, 0, glFormat, glType, (source && source.data) || null); | ||
} | ||
_update_textureCube(_gl, source, level, width, height, depth, glInternalFormat, glFormat, glType) { | ||
for (let i = 0; i < 6; i++) { | ||
const target = cubeTargets[i]; | ||
const img = data.image && data.image[target]; | ||
const pixels = data.pixels && data.pixels[target]; | ||
if (img) { | ||
_gl.texImage2D(constants.TEXTURE_CUBE_MAP_POSITIVE_X + i, level, glInternalFormat, glFormat, glType, img); | ||
const sourceSide = source && source[target]; | ||
const glTarget = constants.TEXTURE_CUBE_MAP_POSITIVE_X + i; | ||
if (isPixelSource(sourceSide) || !sourceSide) { | ||
_gl.texImage2D(glTarget, level, glInternalFormat, width, height, 0, glFormat, glType, (sourceSide && sourceSide.data) || null); | ||
} | ||
else { | ||
_gl.texImage2D(constants.TEXTURE_CUBE_MAP_POSITIVE_X + i, level, glInternalFormat, width, height, 0, glFormat, glType, pixels || null); | ||
_gl.texImage2D(glTarget, level, glInternalFormat, glFormat, glType, sourceSide); | ||
} | ||
@@ -137,5 +152,3 @@ } | ||
_getBindTarget() { | ||
return this._texture.textureType === 'texture2D' | ||
? constants.TEXTURE_2D | ||
: constants.TEXTURE_CUBE_MAP; | ||
return textureTargetMap[this._texture.textureType]; | ||
} | ||
@@ -153,2 +166,5 @@ generateMipmap(gl) { | ||
gl.bindTexture(bindTarget, null); | ||
if (gl.getError()) { | ||
debugger; | ||
} | ||
} | ||
@@ -155,0 +171,0 @@ } |
import { ShaderDefineValue } from '../Shader'; | ||
import GLProgram from './GLProgram'; | ||
import GLRenderer, { GLMaterialObject, GLRenderableObject } from './GLRenderer'; | ||
import GLPipeline, { GLMaterialObject, GLRenderableObject } from './GLPipeline'; | ||
export declare function defaultGetMaterialProgramKey(vertexDefines: Record<string, ShaderDefineValue>, fragmentDefines: Record<string, ShaderDefineValue>, enabledTextures: string[]): string; | ||
declare class ProgramManager { | ||
private _renderer; | ||
private _pipeline; | ||
private _cache; | ||
constructor(renderer: GLRenderer); | ||
constructor(renderer: GLPipeline); | ||
getProgram(renderable: GLRenderableObject, material: GLMaterialObject, extraKey: string, extraDefines?: Record<string, ShaderDefineValue>): GLProgram; | ||
} | ||
export default ProgramManager; |
@@ -75,14 +75,6 @@ import { keys } from '../core/util'; | ||
function getPrecisionCode(precision) { | ||
return (['precision', precision, 'float'].join(' ') + | ||
';\n' + | ||
['precision', precision, 'int'].join(' ') + | ||
';\n' + | ||
// depth texture may have precision problem on iOS device. | ||
['precision', precision, 'sampler2D'].join(' ') + | ||
';\n'); | ||
return ['float', 'int', 'sampler2D', 'sampler2DArray'] | ||
.map((type) => `precision ${precision} ${type};`) | ||
.join('\n'); | ||
} | ||
function defaultGetEnabledTextures(material) { | ||
const uniforms = material.uniforms; | ||
return keys(uniforms).filter((uniformName) => uniforms[uniformName].type === 't' || uniforms[uniformName].type === 'tv'); | ||
} | ||
function getDefineKey(defines) { | ||
@@ -112,7 +104,7 @@ const defineKeys = keys(defines); | ||
this._cache = {}; | ||
this._renderer = renderer; | ||
this._pipeline = renderer; | ||
} | ||
getProgram(renderable, material, extraKey, extraDefines) { | ||
const cache = this._cache; | ||
const renderer = this._renderer; | ||
const renderer = this._pipeline; | ||
const isSkinnedMesh = renderable.isSkinnedMesh && renderable.isSkinnedMesh(); | ||
@@ -119,0 +111,0 @@ const isInstancedMesh = renderable.isInstancedMesh && renderable.isInstancedMesh(); |
@@ -55,3 +55,3 @@ /** | ||
*/ | ||
export declare function identity(out: number[]): number[]; | ||
export declare function identity(out: Mat4Array): Mat4Array; | ||
/** | ||
@@ -233,3 +233,3 @@ * Transpose the values of a mat4 | ||
*/ | ||
export declare function lookAt(out: Mat4Array, eye: Vec3Array, center: Vec3Array, up: Vec3Array): number[]; | ||
export declare function lookAt(out: Mat4Array, eye: Vec3Array, center: Vec3Array, up: Vec3Array): Mat4Array; | ||
/** | ||
@@ -236,0 +236,0 @@ * Returns Frobenius norm of a mat4 |
import { Color } from './core/type'; | ||
import type Mesh from './Mesh'; | ||
import ClayNode, { ClayNodeOpts } from './Node'; | ||
import { UniformType } from './Shader'; | ||
export interface LightOpts extends ClayNodeOpts { | ||
@@ -45,3 +46,3 @@ /** | ||
uniformTemplates?: Record<string, { | ||
type: string; | ||
type: UniformType; | ||
value: (instance: Light) => any; | ||
@@ -48,0 +49,0 @@ }>; |
@@ -11,3 +11,3 @@ import Light from '../Light'; | ||
ambientLightColor: { | ||
type: '3f', | ||
type: 'vec3', | ||
value(instance) { | ||
@@ -14,0 +14,0 @@ const color = instance.color; |
@@ -44,3 +44,3 @@ // https://docs.unrealengine.com/latest/INT/Engine/Rendering/LightingAndShadows/AmbientCubemap/ | ||
ambientCubemapLightColor: { | ||
type: '3f', | ||
type: 'vec3', | ||
value(instance) { | ||
@@ -53,3 +53,3 @@ const color = instance.color; | ||
ambientCubemapLightCubemap: { | ||
type: 't', | ||
type: 'samplerCube', | ||
value(instance) { | ||
@@ -60,3 +60,3 @@ return instance.cubemap; | ||
ambientCubemapLightBRDFLookup: { | ||
type: 't', | ||
type: 'sampler2D', | ||
value(instance) { | ||
@@ -63,0 +63,0 @@ return instance._brdfLookup; |
@@ -17,3 +17,3 @@ import Light from '../Light'; | ||
ambientSHLightColor: { | ||
type: '3f', | ||
type: 'vec3', | ||
value(instance) { | ||
@@ -26,3 +26,3 @@ const color = instance.color; | ||
ambientSHLightCoefficients: { | ||
type: '3f', | ||
type: 'vec3', | ||
value(instance) { | ||
@@ -29,0 +29,0 @@ const coefficientsTmpArr = instance.__coefficientsTmpArr; |
@@ -33,3 +33,3 @@ import { assign } from '../core/util'; | ||
directionalLightDirection: { | ||
type: '3f', | ||
type: 'vec3', | ||
value(instance) { | ||
@@ -42,3 +42,3 @@ const dir = new Vector3(); | ||
directionalLightColor: { | ||
type: '3f', | ||
type: 'vec3', | ||
value(instance) { | ||
@@ -45,0 +45,0 @@ const color = instance.color; |
@@ -19,3 +19,3 @@ import { assign } from '../core/util'; | ||
pointLightPosition: { | ||
type: '3f', | ||
type: 'vec3', | ||
value: function (instance) { | ||
@@ -26,3 +26,3 @@ return instance.getWorldPosition().array; | ||
pointLightRange: { | ||
type: '1f', | ||
type: 'float', | ||
value: function (instance) { | ||
@@ -33,3 +33,3 @@ return instance.range; | ||
pointLightColor: { | ||
type: '3f', | ||
type: 'vec3', | ||
value: function (instance) { | ||
@@ -36,0 +36,0 @@ const color = instance.color; |
@@ -20,3 +20,3 @@ import { assign } from '../core/util'; | ||
sphereLightPosition: { | ||
type: '3f', | ||
type: 'vec3', | ||
value(instance) { | ||
@@ -27,3 +27,3 @@ return instance.getWorldPosition().array; | ||
sphereLightRange: { | ||
type: '1f', | ||
type: 'float', | ||
value(instance) { | ||
@@ -34,3 +34,3 @@ return instance.range; | ||
sphereLightRadius: { | ||
type: '1f', | ||
type: 'float', | ||
value(instance) { | ||
@@ -41,3 +41,3 @@ return instance.radius; | ||
sphereLightColor: { | ||
type: '3f', | ||
type: 'vec3', | ||
value(instance) { | ||
@@ -44,0 +44,0 @@ const color = instance.color; |
@@ -28,3 +28,3 @@ import { assign } from '../core/util'; | ||
spotLightPosition: { | ||
type: '3f', | ||
type: 'vec3', | ||
value(instance) { | ||
@@ -35,3 +35,3 @@ return instance.getWorldPosition().array; | ||
spotLightRange: { | ||
type: '1f', | ||
type: 'float', | ||
value(instance) { | ||
@@ -42,3 +42,3 @@ return instance.range; | ||
spotLightUmbraAngleCosine: { | ||
type: '1f', | ||
type: 'float', | ||
value(instance) { | ||
@@ -49,3 +49,3 @@ return Math.cos((instance.umbraAngle * Math.PI) / 180); | ||
spotLightPenumbraAngleCosine: { | ||
type: '1f', | ||
type: 'float', | ||
value(instance) { | ||
@@ -56,3 +56,3 @@ return Math.cos((instance.penumbraAngle * Math.PI) / 180); | ||
spotLightFalloffFactor: { | ||
type: '1f', | ||
type: 'float', | ||
value(instance) { | ||
@@ -63,3 +63,3 @@ return instance.falloffFactor; | ||
spotLightDirection: { | ||
type: '3f', | ||
type: 'vec3', | ||
value(instance) { | ||
@@ -72,3 +72,3 @@ // TODO | ||
spotLightColor: { | ||
type: '3f', | ||
type: 'vec3', | ||
value(instance) { | ||
@@ -75,0 +75,0 @@ const color = instance.color; |
@@ -21,3 +21,3 @@ import { assign } from '../core/util'; | ||
tubeLightPosition: { | ||
type: '3f', | ||
type: 'vec3', | ||
value: function (instance) { | ||
@@ -28,3 +28,3 @@ return instance.getWorldPosition().array; | ||
tubeLightExtend: { | ||
type: '3f', | ||
type: 'vec3', | ||
value: (function () { | ||
@@ -42,3 +42,3 @@ const x = new Vector3(); | ||
tubeLightRange: { | ||
type: '1f', | ||
type: 'float', | ||
value: function (instance) { | ||
@@ -49,3 +49,3 @@ return instance.range; | ||
tubeLightColor: { | ||
type: '3f', | ||
type: 'vec3', | ||
value: function (instance) { | ||
@@ -52,0 +52,0 @@ const color = instance.color; |
@@ -79,6 +79,2 @@ import Scene from '../Scene'; | ||
textureFlipY: boolean; | ||
/** | ||
* If convert texture to power-of-two | ||
*/ | ||
textureConvertToPOT: boolean; | ||
onload?: (res: GLTFLoadResult) => void; | ||
@@ -85,0 +81,0 @@ onerror?: (err: any) => void; |
@@ -129,4 +129,3 @@ /** | ||
crossOrigin: '', | ||
textureFlipY: false, | ||
textureConvertToPOT: false | ||
textureFlipY: false | ||
}, opts); | ||
@@ -425,4 +424,3 @@ const isBinary = url.endsWith('.glb'); | ||
wrapT: constants.REPEAT, | ||
flipY: opts.textureFlipY, | ||
convertToPOT: opts.textureConvertToPOT | ||
flipY: opts.textureFlipY | ||
}); | ||
@@ -811,2 +809,5 @@ const target = textureInfo.target || constants.TEXTURE_2D; | ||
} | ||
else if (attributeArray instanceof Uint32Array) { | ||
attributeType = 'int'; | ||
} | ||
// TODO | ||
@@ -813,0 +814,0 @@ geometry.attributes[attributeName].type = attributeType; |
@@ -1,3 +0,6 @@ | ||
import Shader, { ShaderDefineValue, ShaderPrecision, ShaderType, VertexShader, FragmentShader, MaterialUniformType } from './Shader'; | ||
import Texture from './Texture'; | ||
import Shader, { ShaderDefineValue, ShaderPrecision, ShaderType, VertexShader, FragmentShader, UniformType } from './Shader'; | ||
import Texture2D from './Texture2D'; | ||
import TextureCube from './TextureCube'; | ||
import Texture2DArray from './Texture2DArray'; | ||
import Texture3D from './Texture3D'; | ||
export interface MaterialOpts { | ||
@@ -28,17 +31,21 @@ name: string; | ||
} | ||
export declare type GeneralMaterialUniformObject = { | ||
type: 't'; | ||
value: Texture; | ||
declare type CreateSamplerMaterialUniformObject<Type, Value> = { | ||
type: Type; | ||
array: false; | ||
value: Value | null; | ||
} | { | ||
type: 'tv'; | ||
value: Texture[]; | ||
} | { | ||
type: Exclude<MaterialUniformType, 't' | 'tv'>; | ||
type: Type; | ||
array: true; | ||
value: Value[] | null; | ||
}; | ||
export declare type GeneralMaterialUniformObject = CreateSamplerMaterialUniformObject<'sampler2D', Texture2D> | CreateSamplerMaterialUniformObject<'samplerCube', TextureCube> | CreateSamplerMaterialUniformObject<'sampler2DArray', Texture2DArray> | CreateSamplerMaterialUniformObject<'sampler3D', Texture3D> | { | ||
type: Exclude<UniformType, 'sampler2D' | 'samplerCube' | 'sampler2DArray' | 'sampler3D'>; | ||
array: boolean; | ||
value: any; | ||
}; | ||
declare type UniformValueRecord<T extends Shader['uniformTpls']> = { | ||
[key in keyof T]?: T[key]['value']; | ||
[key in keyof T]?: T[key]['value'] | null; | ||
}; | ||
declare type PickTextureUniforms<T extends Shader['uniformTpls']> = Pick<T, { | ||
[key in keyof T]: T[key]['type'] extends 't' | 'tv' ? key : never; | ||
[key in keyof T]: T[key]['type'] extends 'sampler2D' | 'samplerCube' ? key : never; | ||
}[keyof T]>; | ||
@@ -80,7 +87,7 @@ interface Material extends Omit<MaterialOpts, 'shader'> { | ||
*/ | ||
set<K extends keyof T['uniformTpls']>(symbol: K, value: T['uniformTpls'][K]['value']): void; | ||
set<K extends keyof T['uniformTpls']>(symbol: K, value: T['uniformTpls'][K]['value'] | null): void; | ||
setUniforms(obj: UniformValueRecord<T['uniformTpls']>): void; | ||
isUniformEnabled(symbol: keyof T['uniformTpls']): boolean; | ||
getEnabledUniforms(): (keyof T['uniformTpls'])[]; | ||
getTextureUniforms(): { [key in keyof T["uniformTpls"]]: T["uniformTpls"][key]["type"] extends "t" | "tv" ? key : never; }[keyof T["uniformTpls"]][]; | ||
getTextureUniforms(): { [key in keyof T["uniformTpls"]]: T["uniformTpls"][key]["type"] extends "sampler2D" | "samplerCube" ? key : never; }[keyof T["uniformTpls"]][]; | ||
/** | ||
@@ -151,3 +158,3 @@ * Get uniform value | ||
*/ | ||
getEnabledTextures(): { [key in keyof T["uniformTpls"]]: T["uniformTpls"][key]["type"] extends "t" | "tv" ? key : never; }[keyof T["uniformTpls"]][]; | ||
getEnabledTextures(): { [key in keyof T["uniformTpls"]]: T["uniformTpls"][key]["type"] extends "sampler2D" | "samplerCube" ? key : never; }[keyof T["uniformTpls"]][]; | ||
/** | ||
@@ -154,0 +161,0 @@ * Mark defines are updated. |
import * as util from './core/util'; | ||
import * as colorUtil from './core/color'; | ||
import { isTextureUniform } from './Shader'; | ||
import { defaultGetMaterialProgramKey } from './gl/ProgramManager'; | ||
@@ -44,6 +45,3 @@ const programKeyCache = {}; | ||
.sort()); | ||
this._textureUniforms = enabledUniforms.filter((uniformName) => { | ||
const type = uniforms[uniformName].type; | ||
return type === 't' || type === 'tv'; | ||
}); | ||
this._textureUniforms = enabledUniforms.filter((uniformName) => isTextureUniform(uniforms[uniformName])); | ||
this.vertexDefines = util.clone(shader.vertexDefines); | ||
@@ -77,5 +75,5 @@ this.fragmentDefines = util.clone(shader.fragmentDefines); | ||
set(symbol, value) { | ||
// PENDING. Should we GIVE WARN when value is undefined? | ||
if (value === undefined) { | ||
return; | ||
// console.warn('Uniform value "' + symbol + '" is undefined'); | ||
} | ||
@@ -86,8 +84,7 @@ const uniform = this.uniforms[symbol]; | ||
// Try to parse as a color. Invalid color string will return null. | ||
// PENDING check rgb/rgba type? | ||
value = colorUtil.parseToFloat(value) || value; | ||
} | ||
uniform.value = value; | ||
if (this.autoUpdateTextureStatus && uniform.type === 't') { | ||
value ? this.enableTexture(symbol) : this.disableTexture(symbol); | ||
if (this.autoUpdateTextureStatus && isTextureUniform(uniform)) { | ||
this[value ? 'enableTexture' : 'disableTexture'](symbol); | ||
} | ||
@@ -94,0 +91,0 @@ } |
@@ -38,6 +38,6 @@ import { FragmentShader, VertexShader } from '../Shader'; | ||
color: { | ||
type: "rgba"; | ||
value: string | import("../glmatrix/common").Vec4Array; | ||
type: "vec4"; | ||
value: import("../glmatrix/common").Vec4Array; | ||
semantic: import("../Shader").UniformSemantic | import("../Shader").MatrixSemantic | undefined; | ||
}; | ||
}, never>; |
@@ -28,3 +28,3 @@ import { createUniform, FragmentShader, glsl, VertexShader } from '../Shader'; | ||
uniforms: { | ||
color: createUniform('rgba', [1, 1, 1, 1]) | ||
color: createUniform('vec4', [1, 1, 1, 1]) | ||
}, | ||
@@ -31,0 +31,0 @@ main: glsl ` |
@@ -51,3 +51,3 @@ import Renderer from '../Renderer'; | ||
*/ | ||
render(renderer: Renderer, scene: Scene, sceneCamera: Camera, notUpdateScene?: boolean): void; | ||
render(renderer: Renderer, scene: Scene, sceneCamera?: Camera, notUpdateScene?: boolean): void; | ||
/** | ||
@@ -54,0 +54,0 @@ * Debug rendering of shadow textures |
@@ -253,8 +253,14 @@ import * as constants from '../core/constants'; | ||
value: directionalLightShadowMaps, | ||
type: 'tv' | ||
type: 'sampler2D', | ||
array: true | ||
}; | ||
shadowUniforms.directionalLightMatrices = { value: directionalLightMatrices, type: 'm4v' }; | ||
shadowUniforms.directionalLightMatrices = { | ||
value: directionalLightMatrices, | ||
type: 'mat4', | ||
array: true | ||
}; | ||
shadowUniforms.directionalLightShadowMapSizes = { | ||
value: directionalLightShadowMapSizes, | ||
type: '1fv' | ||
type: 'float', | ||
array: true | ||
}; | ||
@@ -271,4 +277,12 @@ if (dirLightHasCascade) { | ||
directionalLightMatrices.reverse(); | ||
shadowUniforms.shadowCascadeClipsNear = { value: shadowCascadeClipsNear, type: '1fv' }; | ||
shadowUniforms.shadowCascadeClipsFar = { value: shadowCascadeClipsFar, type: '1fv' }; | ||
shadowUniforms.shadowCascadeClipsNear = { | ||
value: shadowCascadeClipsNear, | ||
type: 'float', | ||
array: true | ||
}; | ||
shadowUniforms.shadowCascadeClipsFar = { | ||
value: shadowCascadeClipsFar, | ||
type: 'float', | ||
array: true | ||
}; | ||
} | ||
@@ -279,8 +293,20 @@ } | ||
const shadowUniforms = scene.shadowUniforms; | ||
shadowUniforms.spotLightShadowMaps = { value: spotLightShadowMaps, type: 'tv' }; | ||
shadowUniforms.spotLightMatrices = { value: spotLightMatrices, type: 'm4v' }; | ||
shadowUniforms.spotLightShadowMapSizes = { value: spotLightShadowMapSizes, type: '1fv' }; | ||
shadowUniforms.spotLightShadowMaps = { | ||
value: spotLightShadowMaps, | ||
type: 'sampler2D', | ||
array: true | ||
}; | ||
shadowUniforms.spotLightMatrices = { value: spotLightMatrices, type: 'mat4', array: true }; | ||
shadowUniforms.spotLightShadowMapSizes = { | ||
value: spotLightShadowMapSizes, | ||
type: 'float', | ||
array: true | ||
}; | ||
} | ||
if (pointLightShadowMaps.length > 0) { | ||
shadowUniforms.pointLightShadowMaps = { value: pointLightShadowMaps, type: 'tv' }; | ||
shadowUniforms.pointLightShadowMaps = { | ||
value: pointLightShadowMaps, | ||
type: 'samplerCube', | ||
array: true | ||
}; | ||
} | ||
@@ -287,0 +313,0 @@ } |
@@ -9,3 +9,3 @@ import Notifier from './core/Notifier'; | ||
import type ClayNode from './Node'; | ||
import { ExtendedRenderableObject, GLRenderableObject, GLRenderHooks } from './gl/GLRenderer'; | ||
import { ExtendedRenderableObject, GLRenderableObject, GLRenderHooks } from './gl/GLPipeline'; | ||
import Texture from './Texture'; | ||
@@ -33,3 +33,3 @@ import InstancedMesh from './InstancedMesh'; | ||
height: number; | ||
devicePixelRatio: number; | ||
pixelRatio: number; | ||
} | ||
@@ -47,3 +47,3 @@ export interface RendererOpts { | ||
/** | ||
* Device pixel ratio, set by setDevicePixelRatio method | ||
* Device pixel ratio, set by setPixelRatio method | ||
* Specially for high defination display | ||
@@ -54,3 +54,3 @@ * @see http://www.khronos.org/webgl/wiki/HandlingHighDPI | ||
*/ | ||
devicePixelRatio: number; | ||
pixelRatio: number; | ||
/** | ||
@@ -116,3 +116,3 @@ * Clear color | ||
/** | ||
* Device pixel ratio, set by setDevicePixelRatio method | ||
* Device pixel ratio, set by setPixelRatio method | ||
* Specially for high defination display | ||
@@ -123,3 +123,3 @@ * @see http://www.khronos.org/webgl/wiki/HandlingHighDPI | ||
*/ | ||
private _devicePixelRatio; | ||
private _pixelRatio; | ||
/** | ||
@@ -137,3 +137,3 @@ * WebGL Context created from given canvas | ||
private _prezMaterial?; | ||
private _glRenderer; | ||
private _glPipeline; | ||
constructor(opts?: Partial<RendererOpts>); | ||
@@ -162,11 +162,11 @@ /** | ||
/** | ||
* Set devicePixelRatio | ||
* @param {number} devicePixelRatio | ||
* Set pixelRatio | ||
* @param {number} pixelRatio | ||
*/ | ||
setDevicePixelRatio(devicePixelRatio: number): void; | ||
setPixelRatio(pixelRatio: number): void; | ||
/** | ||
* Get devicePixelRatio | ||
* @param {number} devicePixelRatio | ||
* Get pixelRatio | ||
* @param {number} pixelRatio | ||
*/ | ||
getDevicePixelRatio(): number; | ||
getPixelRatio(): number; | ||
/** | ||
@@ -178,4 +178,4 @@ * Set rendering viewport | ||
* @param {number} [height] | ||
* @param {number} [devicePixelRatio] | ||
* Defaultly use the renderere devicePixelRatio | ||
* @param {number} [pixelRatio] | ||
* Defaultly use the renderere pixelRatio | ||
* It needs to be 1 when setViewport is called by frameBuffer | ||
@@ -190,3 +190,3 @@ * | ||
* height: height, | ||
* devicePixelRatio: 1 | ||
* pixelRatio: 1 | ||
* }) | ||
@@ -193,0 +193,0 @@ */ |
@@ -9,3 +9,3 @@ // TODO Resources like shader, texture, geometry reference management | ||
// Light header | ||
import Shader, { BASIC_MATRIX_SEMANTICS } from './Shader'; | ||
import Shader, { BASIC_MATRIX_SEMANTICS, isTextureUniform } from './Shader'; | ||
import * as mat4 from './glmatrix/mat4'; | ||
@@ -15,3 +15,3 @@ import * as vec3 from './glmatrix/vec3'; | ||
import { preZFragment, preZVertex } from './shader/source/prez.glsl'; | ||
import GLRenderer from './gl/GLRenderer'; | ||
import GLPipeline from './gl/GLPipeline'; | ||
const mat4Create = mat4.create; | ||
@@ -52,3 +52,3 @@ /** | ||
gl.targetRenderer = this; | ||
this._glRenderer = new GLRenderer(gl, { | ||
this._glPipeline = new GLPipeline(gl, { | ||
throwError: opts.throwError | ||
@@ -58,4 +58,4 @@ }); | ||
this._height = opts.height || canvas.height || 100; | ||
this._devicePixelRatio = | ||
opts.devicePixelRatio || (typeof window !== 'undefined' ? window.devicePixelRatio : 1.0); | ||
this._pixelRatio = | ||
opts.pixelRatio || (typeof window !== 'undefined' ? window.devicePixelRatio : 1.0); | ||
this.resize(this._width, this._height); | ||
@@ -78,3 +78,3 @@ } | ||
const canvas = this.canvas; | ||
const dpr = this._devicePixelRatio; | ||
const dpr = this._pixelRatio; | ||
if (width != null) { | ||
@@ -114,15 +114,15 @@ setCanvasSize(canvas, width, height, dpr); | ||
/** | ||
* Set devicePixelRatio | ||
* @param {number} devicePixelRatio | ||
* Set pixelRatio | ||
* @param {number} pixelRatio | ||
*/ | ||
setDevicePixelRatio(devicePixelRatio) { | ||
this._devicePixelRatio = devicePixelRatio; | ||
setPixelRatio(pixelRatio) { | ||
this._pixelRatio = pixelRatio; | ||
this.resize(this._width, this._height); | ||
} | ||
/** | ||
* Get devicePixelRatio | ||
* @param {number} devicePixelRatio | ||
* Get pixelRatio | ||
* @param {number} pixelRatio | ||
*/ | ||
getDevicePixelRatio() { | ||
return this._devicePixelRatio; | ||
getPixelRatio() { | ||
return this._pixelRatio; | ||
} | ||
@@ -136,6 +136,6 @@ setViewport(x, y, width, height, dpr) { | ||
height = obj.height; | ||
dpr = obj.devicePixelRatio; | ||
dpr = obj.pixelRatio; | ||
} | ||
dpr = dpr || this._devicePixelRatio; | ||
this._glRenderer.setViewport(x, y, width, height, dpr); | ||
dpr = dpr || this._pixelRatio; | ||
this._glPipeline.setViewport(x, y, width, height, dpr); | ||
// Use a fresh new object, not write property. | ||
@@ -147,3 +147,3 @@ this.viewport = { | ||
height: height, | ||
devicePixelRatio: dpr | ||
pixelRatio: dpr | ||
}; | ||
@@ -186,3 +186,3 @@ } | ||
getWebGLExtension(name) { | ||
return this._glRenderer.getWebGLExtension(name); | ||
return this._glPipeline.getWebGLExtension(name); | ||
} | ||
@@ -198,4 +198,4 @@ /** | ||
const { notUpdateScene, preZ } = opts; | ||
const viewport = this._glRenderer.getViewport(); | ||
const viewportDpr = viewport.devicePixelRatio; | ||
const viewport = this._glPipeline.getViewport(); | ||
const viewportDpr = viewport.pixelRatio; | ||
if (this.clearBit) { | ||
@@ -208,3 +208,3 @@ // Must set depth and color mask true before clear | ||
viewport.height !== this._height || | ||
(viewportDpr && viewportDpr !== this._devicePixelRatio) || | ||
(viewportDpr && viewportDpr !== this._pixelRatio) || | ||
viewport.x || | ||
@@ -291,11 +291,11 @@ viewport.y) { | ||
_bindFrameBuffer(frameBuffer) { | ||
const glRenderer = this._glRenderer; | ||
glRenderer.bindFrameBuffer(frameBuffer); | ||
const glPipeline = this._glPipeline; | ||
glPipeline.bindFrameBuffer(frameBuffer); | ||
const viewport = frameBuffer ? frameBuffer.getViewport() : this.viewport; | ||
glRenderer.setViewport(viewport.x, viewport.y, viewport.width, viewport.height, viewport.devicePixelRatio); | ||
glPipeline.setViewport(viewport.x, viewport.y, viewport.width, viewport.height, viewport.pixelRatio); | ||
} | ||
_renderPass(list, camera, frameBuffer, renderHooks, scene) { | ||
let worldM; | ||
const viewport = this._glRenderer.getViewport(); | ||
const vDpr = viewport.devicePixelRatio; | ||
const viewport = this._glPipeline.getViewport(); | ||
const vDpr = viewport.pixelRatio; | ||
const viewportUniform = [ | ||
@@ -307,7 +307,6 @@ viewport.x * vDpr, | ||
]; | ||
const windowDpr = this._devicePixelRatio; | ||
const windowDpr = this._pixelRatio; | ||
const windowSizeUniform = frameBuffer | ||
? [frameBuffer.getWidth(), frameBuffer.getHeight()] | ||
: [this._width * windowDpr, this._height * windowDpr]; | ||
// DEPRECATED | ||
const viewportSizeUniform = [viewportUniform[2], viewportUniform[3]]; | ||
@@ -334,3 +333,3 @@ const time = Date.now(); | ||
let key = (scene && scene.getProgramKey(renderable.lightGroup || 0)) || ''; | ||
if (this.logDepthBuffer) { | ||
if (logDepthBuffer) { | ||
key += ',ld'; | ||
@@ -351,2 +350,5 @@ } | ||
} | ||
if (logDepthBuffer) { | ||
extraDefines.LOG_DEPTH = true; | ||
} | ||
return extraDefines; | ||
@@ -411,3 +413,3 @@ }, | ||
// And we share reference between renderables. | ||
program.set(gl, semanticInfo.type, semanticInfo.name, matrix, true); | ||
program.set(gl, semanticInfo.type, semanticInfo.name, matrix, false, true); | ||
} | ||
@@ -417,12 +419,12 @@ } | ||
// Do frmaebuffer bind in the rnderPass method exposed to outside. | ||
this._glRenderer.bindFrameBuffer(frameBuffer); | ||
this._glPipeline.bindFrameBuffer(frameBuffer); | ||
renderHooks && renderHooks.prepare && renderHooks.prepare(gl); | ||
this._glRenderer.render(list, assign(renderHooksForScene, renderHooks)); | ||
this._glPipeline.render(list, assign(renderHooksForScene, renderHooks)); | ||
renderHooks && renderHooks.cleanup && renderHooks.cleanup(gl); | ||
} | ||
getMaxJointNumber() { | ||
return this._glRenderer.maxJointNumber; | ||
return this._glPipeline.maxJointNumber; | ||
} | ||
setMaxJointNumber(val) { | ||
this._glRenderer.maxJointNumber = val; | ||
this._glPipeline.maxJointNumber = val; | ||
} | ||
@@ -498,7 +500,7 @@ renderPreZ(list, scene, camera) { | ||
const disposedMap = {}; | ||
const glRenderer = this._glRenderer; | ||
const glPipeline = this._glPipeline; | ||
root.traverse((node) => { | ||
const material = node.material; | ||
if (node.geometry && disposeGeometry) { | ||
this._glRenderer.disposeGeometry(node.geometry); | ||
this._glPipeline.disposeGeometry(node.geometry); | ||
} | ||
@@ -513,16 +515,19 @@ // Pending more check? | ||
const uniformName = textureUniforms[u]; | ||
const val = material.uniforms[uniformName].value; | ||
const uniformType = material.uniforms[uniformName].type; | ||
const uniformObj = material.uniforms[uniformName]; | ||
const val = uniformObj.value; | ||
const uniformType = uniformObj.type; | ||
if (!val) { | ||
continue; | ||
} | ||
if (uniformType === 't') { | ||
glRenderer.disposeTexture(val); | ||
} | ||
else if (uniformType === 'tv') { | ||
for (let k = 0; k < val.length; k++) { | ||
if (val[k]) { | ||
glRenderer.disposeTexture(val[k]); | ||
if (isTextureUniform(uniformObj)) { | ||
if (uniformObj.array) { | ||
for (let k = 0; k < val.length; k++) { | ||
if (val[k]) { | ||
glPipeline.disposeTexture(val[k]); | ||
} | ||
} | ||
} | ||
else { | ||
glPipeline.disposeTexture(val); | ||
} | ||
} | ||
@@ -537,12 +542,12 @@ } | ||
disposeTexture(texture) { | ||
this._glRenderer.disposeTexture(texture); | ||
this._glPipeline.disposeTexture(texture); | ||
} | ||
disposeGeometry(geometry) { | ||
this._glRenderer.disposeGeometry(geometry); | ||
this._glPipeline.disposeGeometry(geometry); | ||
} | ||
disposeFrameBuffer(frameBuffer) { | ||
this._glRenderer.disposeFrameBuffer(frameBuffer); | ||
this._glPipeline.disposeFrameBuffer(frameBuffer); | ||
} | ||
disposeInstancedMesh(mesh) { | ||
this._glRenderer.disposeInstancedMesh(mesh); | ||
this._glPipeline.disposeInstancedMesh(mesh); | ||
} | ||
@@ -549,0 +554,0 @@ /** |
@@ -8,4 +8,4 @@ import ClayNode, { ClayNodeOpts } from './Node'; | ||
import type Material from './Material'; | ||
import { MaterialUniform } from './Shader'; | ||
import Skybox from './Skybox'; | ||
import { GeneralMaterialUniformObject } from './Material'; | ||
export declare class RenderList { | ||
@@ -38,3 +38,3 @@ opaque: Renderable[]; | ||
viewBoundingBoxLastFrame: BoundingBox; | ||
shadowUniforms: Record<string, MaterialUniform>; | ||
shadowUniforms: Record<string, GeneralMaterialUniformObject>; | ||
skybox?: Skybox; | ||
@@ -101,3 +101,3 @@ private _cameraList; | ||
getProgramKey(lightGroup: number): string; | ||
getLightUniforms(lightGroup: number): Record<string, MaterialUniform>[]; | ||
getLightUniforms(lightGroup: number): Record<string, GeneralMaterialUniformObject>[]; | ||
/** | ||
@@ -104,0 +104,0 @@ * Dispose self, clear all the scene objects |
@@ -331,2 +331,4 @@ import ClayNode from './Node'; | ||
lightUniforms[group][symbol] = { | ||
type: uniformTpl.type, | ||
array: true, | ||
value: [] | ||
@@ -336,12 +338,12 @@ }; | ||
const lu = lightUniforms[group][symbol]; | ||
lu.type = (uniformTpl.type + 'v'); | ||
switch (uniformTpl.type) { | ||
case '1i': | ||
case '1f': | ||
case 't': | ||
case 'int': | ||
case 'float': | ||
case 'sampler2D': | ||
case 'samplerCube': | ||
lu.value.push(value); | ||
break; | ||
case '2f': | ||
case '3f': | ||
case '4f': | ||
case 'vec2': | ||
case 'vec3': | ||
case 'vec4': | ||
for (let j = 0; j < value.length; j++) { | ||
@@ -348,0 +350,0 @@ lu.value.push(value[j]); |
import { Dict, UnionToIntersection } from './core/type'; | ||
import { mat2, mat3, mat4, vec2, vec3, vec4 } from './glmatrix'; | ||
import Texture2D from './Texture2D'; | ||
import Texture2DArray from './Texture2DArray'; | ||
import Texture3D from './Texture3D'; | ||
import TextureCube from './TextureCube'; | ||
@@ -8,22 +10,14 @@ export declare type ShaderDefineValue = boolean | string | number | undefined | null; | ||
export declare type ShaderType = 'vertex' | 'fragment'; | ||
declare const uniformTypeMap: { | ||
readonly bool: "1i"; | ||
readonly int: "1i"; | ||
readonly sampler2D: "t"; | ||
readonly samplerCube: "t"; | ||
readonly float: "1f"; | ||
readonly vec2: "2f"; | ||
readonly vec3: "3f"; | ||
readonly vec4: "4f"; | ||
readonly ivec2: "2i"; | ||
readonly ivec3: "3i"; | ||
readonly ivec4: "4i"; | ||
readonly mat2: "m2"; | ||
readonly mat3: "m3"; | ||
readonly mat4: "m4"; | ||
readonly rgb: "3f"; | ||
readonly rgba: "4f"; | ||
export declare type UniformType = 'bool' | 'int' | 'sampler2D' | 'sampler2DArray' | 'sampler3D' | 'samplerCube' | 'float' | 'vec2' | 'vec3' | 'vec4' | 'ivec2' | 'ivec3' | 'ivec4' | 'mat2' | 'mat3' | 'mat4'; | ||
export declare type NativeUniformType = Exclude<UniformType, '_struct'>; | ||
declare const attributeSizeMap: { | ||
readonly vec2: 2; | ||
readonly vec3: 3; | ||
readonly vec4: 4; | ||
readonly ivec2: 2; | ||
readonly ivec3: 3; | ||
readonly ivec4: 4; | ||
readonly float: 1; | ||
readonly int: 1; | ||
}; | ||
declare type NativeToMaterialUniformTypeMap = typeof uniformTypeMap; | ||
declare type NativeUniformType = keyof NativeToMaterialUniformTypeMap; | ||
declare type NativeUniformValueMap = { | ||
@@ -34,2 +28,4 @@ bool: number; | ||
samplerCube: TextureCube; | ||
sampler3D: Texture3D; | ||
sampler2DArray: Texture2DArray; | ||
float: number; | ||
@@ -45,4 +41,2 @@ vec2: vec2.Vec2Array; | ||
mat4: mat4.Mat4Array; | ||
rgb: vec3.Vec3Array | string; | ||
rgba: vec4.Vec4Array | string; | ||
}; | ||
@@ -54,2 +48,4 @@ declare type NativeUniformArrayValueMap = { | ||
samplerCube: TextureCube[]; | ||
sampler3D: Texture3D[]; | ||
sampler2DArray: Texture2DArray[]; | ||
float: ArrayLike<number>; | ||
@@ -65,26 +61,5 @@ vec2: ArrayLike<number>; | ||
mat4: ArrayLike<number>; | ||
rgb: ArrayLike<number>; | ||
rgba: ArrayLike<number>; | ||
}; | ||
declare type NativeAttributeType = 'float' | 'vec2' | 'vec3' | 'vec4'; | ||
declare type NativeToMaterialUniformArrayTypeMap = { | ||
bool: '1iv'; | ||
int: '1iv'; | ||
sampler2D: 'tv'; | ||
samplerCube: 'tv'; | ||
float: '1fv'; | ||
vec2: '2fv'; | ||
vec3: '3fv'; | ||
vec4: '4fv'; | ||
ivec2: '2iv'; | ||
ivec3: '3iv'; | ||
ivec4: '4iv'; | ||
mat2: 'm2v'; | ||
mat3: 'm3v'; | ||
mat4: 'm4v'; | ||
rgb: '3fv'; | ||
rgba: '4fv'; | ||
}; | ||
export declare type MaterialUniformType = NativeToMaterialUniformTypeMap[NativeUniformType] | NativeToMaterialUniformArrayTypeMap[keyof NativeToMaterialUniformArrayTypeMap]; | ||
export declare type AttributeSemantic = 'POSITION' | 'NORMAL' | 'BINORMAL' | 'TANGENT' | 'TEXCOORD' | 'TEXCOORD_0' | 'TEXCOORD_1' | 'COLOR' | 'JOINT' | 'WEIGHT'; | ||
declare type NativeAttributeType = keyof typeof attributeSizeMap; | ||
export declare type AttributeSemantic = 'POSITION' | 'NORMAL' | 'BINORMAL' | 'TANGENT' | 'TEXCOORD_0' | 'TEXCOORD_1' | 'COLOR' | 'JOINT' | 'WEIGHT'; | ||
export declare type UniformSemantic = 'VIEWPORT_SIZE' | 'VIEWPORT' | 'DEVICEPIXELRATIO' | 'WINDOW_SIZE' | 'NEAR' | 'FAR' | 'TIME' | 'LOG_DEPTH_BUFFER_FC'; | ||
@@ -94,10 +69,5 @@ export declare const BASIC_MATRIX_SEMANTICS: readonly ["WORLD", "VIEW", "PROJECTION", "WORLDVIEW", "VIEWPROJECTION", "WORLDVIEWPROJECTION"]; | ||
export declare type MatrixSemantic = MatrixSemanticNoTranpose | 'WORLDTRANSPOSE' | 'VIEWTRANSPOSE' | 'PROJECTIONTRANSPOSE' | 'WORLDVIEWTRANSPOSE' | 'VIEWPROJECTIONTRANSPOSE' | 'WORLDVIEWPROJECTIONTRANSPOSE' | 'WORLDINVERSETRANSPOSE' | 'VIEWINVERSETRANSPOSE' | 'PROJECTIONINVERSETRANSPOSE' | 'WORLDVIEWINVERSETRANSPOSE' | 'VIEWPROJECTIONINVERSETRANSPOSE' | 'WORLDVIEWPROJECTIONINVERSETRANSPOSE'; | ||
export interface MaterialUniform { | ||
type: MaterialUniformType; | ||
value: any; | ||
semantic?: string; | ||
} | ||
export declare function glsl(strings: TemplateStringsArray, ...values: string[]): string; | ||
declare type ShaderUniformLoose = { | ||
type: NativeUniformType; | ||
type: UniformType; | ||
value?: unknown; | ||
@@ -113,3 +83,3 @@ semantic?: AttributeSemantic | UniformSemantic | MatrixSemantic; | ||
declare type ShaderVaringLoose = { | ||
type: NativeUniformType; | ||
type: UniformType; | ||
}; | ||
@@ -121,3 +91,3 @@ export declare function createUniform<T extends NativeUniformType, S extends MatrixSemantic | UniformSemantic>(type: T, value?: Exclude<NativeUniformValueMap[T], string>, semantic?: S): { | ||
}; | ||
export declare function createSemanticUniform<T extends NativeUniformType, S extends MatrixSemantic | UniformSemantic>(type: T, semantic: S): { | ||
export declare function createSemanticUniform<T extends UniformType, S extends MatrixSemantic | UniformSemantic>(type: T, semantic: S): { | ||
type: T; | ||
@@ -137,3 +107,3 @@ semantic: S; | ||
}; | ||
export declare function createVarying<T extends NativeUniformType>(type: T): { | ||
export declare function createVarying<T extends UniformType>(type: T): { | ||
type: T; | ||
@@ -228,9 +198,2 @@ }; | ||
} | ||
declare type ConvertShaderUniformToMaterialUniform<T extends Dict<ShaderUniformLoose>> = { | ||
[key in keyof T]: { | ||
value: T[key]['value']; | ||
type: T[key]['array'] extends true ? NativeToMaterialUniformArrayTypeMap[T[key]['type']] : NativeToMaterialUniformTypeMap[T[key]['type']]; | ||
semantic?: T[key]['semantic']; | ||
}; | ||
}; | ||
export declare type VertexShaderLoose = VertexShader<Dict<ShaderDefineValue>, Dict<ShaderUniformLoose>, Dict<ShaderAttributeLoose>, Dict<ShaderVaringLoose>>; | ||
@@ -251,3 +214,3 @@ export declare type FragmentShaderLoose = FragmentShader<Dict<ShaderDefineValue>, Dict<ShaderUniformLoose>>; | ||
*/ | ||
readonly uniformTpls: ConvertShaderUniformToMaterialUniform<V['uniforms'] & F['uniforms']>; | ||
readonly uniformTpls: V['uniforms'] & F['uniforms']; | ||
/** | ||
@@ -257,3 +220,3 @@ * Processed attributes for geometry | ||
readonly attributes: Record<string, { | ||
type: 'float'; | ||
type: 'float' | 'int'; | ||
size: number; | ||
@@ -266,3 +229,3 @@ semantic?: string; | ||
name: string; | ||
type: MaterialUniformType; | ||
type: UniformType; | ||
isTranspose?: boolean; | ||
@@ -278,3 +241,3 @@ isInverse?: boolean; | ||
get shaderID(): string; | ||
createUniforms(): ConvertShaderUniformToMaterialUniform<V["uniforms"] & F["uniforms"]>; | ||
createUniforms(): V["uniforms"] & F["uniforms"]; | ||
constructor(vert: V, frag: F); | ||
@@ -289,2 +252,5 @@ static uniform: typeof createUniform; | ||
} | ||
export declare function isTextureUniform(uniform: { | ||
type: UniformType; | ||
}): boolean; | ||
export default Shader; |
@@ -6,21 +6,2 @@ // TODO check if name of varyings, uniforms, attributes conflicts | ||
import { assign, genGUID, isString, keys } from './core/util'; | ||
const uniformTypeMap = { | ||
bool: '1i', | ||
int: '1i', | ||
sampler2D: 't', | ||
samplerCube: 't', | ||
float: '1f', | ||
vec2: '2f', | ||
vec3: '3f', | ||
vec4: '4f', | ||
ivec2: '2i', | ||
ivec3: '3i', | ||
ivec4: '4i', | ||
mat2: 'm2', | ||
mat3: 'm3', | ||
mat4: 'm4', | ||
// It's not builtin glsl type. But a special type that support string and will be parsed in material | ||
rgb: '3f', | ||
rgba: '4f' | ||
}; | ||
const attributeSizeMap = { | ||
@@ -30,3 +11,7 @@ vec2: 2, | ||
vec4: 4, | ||
float: 1 | ||
ivec2: 2, | ||
ivec3: 3, | ||
ivec4: 4, | ||
float: 1, | ||
int: 1 | ||
}; | ||
@@ -41,2 +26,7 @@ export const BASIC_MATRIX_SEMANTICS = [ | ||
]; | ||
// type ShaderUniform<T extends UniformType> = { | ||
// type: T; | ||
// value: NativeUniformValueMap[T]; | ||
// semantic?: string; | ||
// }; | ||
// Tagged template | ||
@@ -53,2 +43,14 @@ export function glsl(strings, ...values) { | ||
} | ||
// export function createStructUniform< | ||
// T extends Record<string, NativeUniformType>, | ||
// S extends number | string | undefined | ||
// >(struct: T, value?: Record<keyof T, NativeUniformValueMap[T[keyof T]]>, len?: S) { | ||
// return { | ||
// type: '_struct' as const, | ||
// struct, | ||
// value, | ||
// len, | ||
// array: !!len as S extends undefined ? false : true | ||
// }; | ||
// } | ||
export function createUniform(type, value, semantic) { | ||
@@ -154,9 +156,19 @@ return { | ||
function composeShaderString(stageShader, isVertex) { | ||
function getStructName(symbol) { | ||
return '__Struct' + symbol[0].toUpperCase() + symbol.slice(1); | ||
} | ||
// function composeStruct(struct: ShaderUniformLoose['struct'], symbol: string) { | ||
// return struct | ||
// ? `struct ${getStructName(symbol)} { | ||
// ${keys(struct) | ||
// .map((key) => ` ${struct[key]} ${key};`) | ||
// .join('\n')} | ||
// } | ||
// ` | ||
// : ''; | ||
// } | ||
// TODO If compose based on #ifdef condition. | ||
function normalizeUniformType(type) { | ||
return type === 'rgb' ? 'vec3' : type === 'rgba' ? 'vec4' : type; | ||
} | ||
// Only compose the uniform, attributes, varying, and codes. | ||
// Defines will be composed dynamically in GLProgram based on the material | ||
function composePart(varType, obj) { | ||
function composePart(varType, obj, isVaring) { | ||
return keys(obj) | ||
@@ -168,4 +180,8 @@ .map((symbol) => { | ||
const arrayExpr = item.array ? `[${item.len}]` : ''; | ||
const needsFlat = isVaring && item.type.startsWith('i'); | ||
return ((isDefinedLen ? `#ifdef ${item.len}\n` : '') + | ||
`${varType} ${normalizeUniformType(item.type)} ${symbol}${arrayExpr};` + | ||
// `${composeStruct(item.struct, symbol)}` + | ||
`${needsFlat ? 'flat ' : ''}${varType} ${ | ||
// item.struct ? getStructName(symbol) : | ||
item.type} ${symbol}${arrayExpr};` + | ||
(isDefinedLen ? `\n#endif` : '')); | ||
@@ -184,3 +200,3 @@ }) | ||
${composePart('in', stageShader.attributes)} | ||
${composePart(isVertex ? 'out' : 'in', stageShader.varyings)} | ||
${composePart(isVertex ? 'out' : 'in', stageShader.varyings, true)} | ||
${stageShader.functions.map((func) => func()).join('\n')} | ||
@@ -191,7 +207,5 @@ | ||
} | ||
function cloneUniformVal(type, val) { | ||
function cloneUniformVal(type, array, val) { | ||
if (val && val.length != null) { | ||
return type.endsWith('v') | ||
? val.map((item) => cloneUniformVal(type.slice(0, -1), item)) | ||
: Array.from(val); | ||
return array ? val.map((item) => cloneUniformVal(type, false, item)) : Array.from(val); | ||
} | ||
@@ -235,3 +249,4 @@ return val; | ||
name: uniformName, | ||
type: (uniformTypeMap[uniformType] + (uniform.array ? 'v' : '')) | ||
array: uniform.array || false, | ||
type: uniformType | ||
}; | ||
@@ -248,3 +263,5 @@ if (uniformSemantic) { | ||
// TODO more generic way? | ||
if (isTranpose || isInverse || BASIC_MATRIX_SEMANTICS.includes(uniformSemantic)) { | ||
if (isTranpose || | ||
isInverse || | ||
BASIC_MATRIX_SEMANTICS.indexOf(uniformSemantic) >= 0) { | ||
matrixSemantics.push(uniformSemantic); | ||
@@ -254,8 +271,2 @@ } | ||
else { | ||
// don't support string color to be default value. | ||
// Avoid including color as core module. | ||
// (materialUniformObj as any).value = | ||
// (uniformType === 'rgb' || uniformType === 'rgba') && isString(uniformValue) | ||
// ? parseToFloat(uniformValue) | ||
// : uniformValue; | ||
materialUniformObj.value = uniformValue; | ||
@@ -280,3 +291,3 @@ // semantic uniform can't be set in material. | ||
attributes[attrName] = { | ||
type: 'float', | ||
type: attrName.startsWith('i') ? 'int' : 'float', | ||
semantic, | ||
@@ -309,3 +320,4 @@ size: attributeSizeMap[attr.type] | ||
type: tpl.type, | ||
value: cloneUniformVal(tpl.type, tpl.value) // Default value? | ||
array: tpl.array, | ||
value: cloneUniformVal(tpl.type, tpl.array, tpl.value) // Default value? | ||
}; | ||
@@ -318,2 +330,3 @@ }); | ||
Shader.arrayUniform = createArrayUniform; | ||
// static structUniform = createStructUniform; | ||
Shader.attribute = createAttribute; | ||
@@ -324,3 +337,6 @@ Shader.varying = createVarying; | ||
Shader.Fragment = FragmentShader; | ||
export function isTextureUniform(uniform) { | ||
return uniform.type.startsWith('sampler'); | ||
} | ||
export default Shader; | ||
//# sourceMappingURL=Shader.js.map |
@@ -73,11 +73,11 @@ import Shader from '../Shader'; | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat2: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat3: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
@@ -114,4 +114,4 @@ }; | ||
color: { | ||
type: "rgb"; | ||
value: string | import("../glmatrix/common").Vec3Array; | ||
type: "vec3"; | ||
value: import("../glmatrix/common").Vec3Array; | ||
semantic: import("../Shader").UniformSemantic | import("../Shader").MatrixSemantic | undefined; | ||
@@ -140,4 +140,4 @@ }; | ||
lineColor: { | ||
type: "rgba"; | ||
value: string | import("../glmatrix/common").Vec4Array; | ||
type: "vec4"; | ||
value: import("../glmatrix/common").Vec4Array; | ||
semantic: import("../Shader").UniformSemantic | import("../Shader").MatrixSemantic | undefined; | ||
@@ -398,4 +398,4 @@ }; | ||
color: { | ||
type: "rgb"; | ||
value: string | import("../glmatrix/common").Vec3Array; | ||
type: "vec3"; | ||
value: import("../glmatrix/common").Vec3Array; | ||
semantic: import("../Shader").UniformSemantic | import("../Shader").MatrixSemantic | undefined; | ||
@@ -507,11 +507,11 @@ }; | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat2: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat3: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
@@ -548,4 +548,4 @@ }; | ||
color: { | ||
type: "rgb"; | ||
value: string | import("../glmatrix/common").Vec3Array; | ||
type: "vec3"; | ||
value: import("../glmatrix/common").Vec3Array; | ||
semantic: import("../Shader").UniformSemantic | import("../Shader").MatrixSemantic | undefined; | ||
@@ -574,4 +574,4 @@ }; | ||
lineColor: { | ||
type: "rgba"; | ||
value: string | import("../glmatrix/common").Vec4Array; | ||
type: "vec4"; | ||
value: import("../glmatrix/common").Vec4Array; | ||
semantic: import("../Shader").UniformSemantic | import("../Shader").MatrixSemantic | undefined; | ||
@@ -603,3 +603,3 @@ }; | ||
type: "vec3"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
@@ -642,11 +642,11 @@ }, { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat2: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat3: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
@@ -659,4 +659,4 @@ }; | ||
color: { | ||
type: "rgb"; | ||
value: string | import("../glmatrix/common").Vec3Array; | ||
type: "vec3"; | ||
value: import("../glmatrix/common").Vec3Array; | ||
semantic: import("../Shader").UniformSemantic | import("../Shader").MatrixSemantic | undefined; | ||
@@ -663,0 +663,0 @@ }; |
@@ -69,4 +69,4 @@ import { VertexShader, FragmentShader } from '../../Shader'; | ||
color: { | ||
type: "rgb"; | ||
value: string | import("../../glmatrix/common").Vec3Array; | ||
type: "vec3"; | ||
value: import("../../glmatrix/common").Vec3Array; | ||
semantic: import("../../Shader").UniformSemantic | import("../../Shader").MatrixSemantic | undefined; | ||
@@ -95,4 +95,4 @@ }; | ||
lineColor: { | ||
type: "rgba"; | ||
value: string | import("../../glmatrix/common").Vec4Array; | ||
type: "vec4"; | ||
value: import("../../glmatrix/common").Vec4Array; | ||
semantic: import("../../Shader").UniformSemantic | import("../../Shader").MatrixSemantic | undefined; | ||
@@ -187,11 +187,11 @@ }; | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat2: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat3: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
@@ -229,4 +229,4 @@ }; | ||
color: { | ||
type: "rgb"; | ||
value: string | import("../../glmatrix/common").Vec3Array; | ||
type: "vec3"; | ||
value: import("../../glmatrix/common").Vec3Array; | ||
semantic: import("../../Shader").UniformSemantic | import("../../Shader").MatrixSemantic | undefined; | ||
@@ -255,4 +255,4 @@ }; | ||
lineColor: { | ||
type: "rgba"; | ||
value: string | import("../../glmatrix/common").Vec4Array; | ||
type: "vec4"; | ||
value: import("../../glmatrix/common").Vec4Array; | ||
semantic: import("../../Shader").UniformSemantic | import("../../Shader").MatrixSemantic | undefined; | ||
@@ -259,0 +259,0 @@ }; |
@@ -62,11 +62,11 @@ import { VertexShader, FragmentShader } from '../../Shader'; | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat2: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat3: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
@@ -73,0 +73,0 @@ }; |
@@ -62,11 +62,11 @@ import { VertexShader, FragmentShader } from '../../Shader'; | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat2: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat3: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
@@ -73,0 +73,0 @@ }; |
@@ -248,4 +248,4 @@ import { VertexShader, FragmentShader } from '../../Shader'; | ||
color: { | ||
type: "rgb"; | ||
value: string | import("../../glmatrix/common").Vec3Array; | ||
type: "vec3"; | ||
value: import("../../glmatrix/common").Vec3Array; | ||
semantic: import("../../Shader").UniformSemantic | import("../../Shader").MatrixSemantic | undefined; | ||
@@ -252,0 +252,0 @@ }; |
@@ -91,11 +91,11 @@ import { FragmentShader, VertexShader } from '../../Shader'; | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat2: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat3: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
@@ -131,4 +131,4 @@ }; | ||
color: { | ||
type: "rgb"; | ||
value: string | import("../../glmatrix/common").Vec3Array; | ||
type: "vec3"; | ||
value: import("../../glmatrix/common").Vec3Array; | ||
semantic: import("../../Shader").UniformSemantic | import("../../Shader").MatrixSemantic | undefined; | ||
@@ -157,4 +157,4 @@ }; | ||
lineColor: { | ||
type: "rgba"; | ||
value: string | import("../../glmatrix/common").Vec4Array; | ||
type: "vec4"; | ||
value: import("../../glmatrix/common").Vec4Array; | ||
semantic: import("../../Shader").UniformSemantic | import("../../Shader").MatrixSemantic | undefined; | ||
@@ -172,4 +172,4 @@ }; | ||
color: { | ||
type: "rgb"; | ||
value: string | import("../../glmatrix/common").Vec3Array; | ||
type: "vec3"; | ||
value: import("../../glmatrix/common").Vec3Array; | ||
semantic: import("../../Shader").UniformSemantic | import("../../Shader").MatrixSemantic | undefined; | ||
@@ -198,4 +198,4 @@ }; | ||
lineColor: { | ||
type: "rgba"; | ||
value: string | import("../../glmatrix/common").Vec4Array; | ||
type: "vec4"; | ||
value: import("../../glmatrix/common").Vec4Array; | ||
semantic: import("../../Shader").UniformSemantic | import("../../Shader").MatrixSemantic | undefined; | ||
@@ -202,0 +202,0 @@ }; |
@@ -53,3 +53,3 @@ import { createAttribute as attribute, createUniform as uniform, createVarying as varying, FragmentShader, glsl, VertexShader } from '../../Shader'; | ||
diffuseMap: uniform('sampler2D'), | ||
color: uniform('rgb', [1, 1, 1]), | ||
color: uniform('vec3', [1, 1, 1]), | ||
emission: uniform('vec3', [0, 0, 0]), | ||
@@ -59,3 +59,3 @@ alpha: uniform('float', 1), | ||
lineWidth: uniform('float', 0), | ||
lineColor: uniform('rgba', [0, 0, 0, 0.6]) | ||
lineColor: uniform('vec4', [0, 0, 0, 0.6]) | ||
}; | ||
@@ -62,0 +62,0 @@ export const unlitFragment = new FragmentShader({ |
@@ -158,11 +158,11 @@ /** | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat2: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat3: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
@@ -169,0 +169,0 @@ }; |
@@ -296,3 +296,3 @@ import { createShaderMixin, glsl, createVarying as varying, createUniform as uniform, createArrayUniform as arrayUniform, createAttribute as attribute, createShaderFunction, FUNCTION_NAME_PLACEHOLDER } from '../../Shader'; | ||
main: glsl ` | ||
#if defined(LOG_DEPTH) | ||
#ifdef LOG_DEPTH | ||
gl_FragDepth = log2(v_FragDepth) * logDepthBufFC * 0.5; | ||
@@ -299,0 +299,0 @@ #endif |
@@ -18,3 +18,3 @@ import { FragmentShader, VertexShader } from '../../Shader'; | ||
type: "vec3"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
@@ -57,11 +57,11 @@ }, { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat2: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
instanceMat3: { | ||
type: "vec4"; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
semantic: "POSITION" | "NORMAL" | "BINORMAL" | "TANGENT" | "TEXCOORD_0" | "TEXCOORD_1" | "COLOR" | "JOINT" | "WEIGHT" | undefined; | ||
}; | ||
@@ -75,4 +75,4 @@ }; | ||
color: { | ||
type: "rgb"; | ||
value: string | import("../../glmatrix/common").Vec3Array; | ||
type: "vec3"; | ||
value: import("../../glmatrix/common").Vec3Array; | ||
semantic: import("../../Shader").UniformSemantic | import("../../Shader").MatrixSemantic | undefined; | ||
@@ -79,0 +79,0 @@ }; |
@@ -38,3 +38,3 @@ import { createAttribute as attribute, createUniform as uniform, createVarying as varying, FragmentShader, glsl, VertexShader } from '../../Shader'; | ||
uniforms: { | ||
color: uniform('rgb', [0, 0, 0]), | ||
color: uniform('vec3', [0, 0, 0]), | ||
alpha: uniform('float', 1), | ||
@@ -41,0 +41,0 @@ lineWidth: uniform('float', 0) |
import Joint from './Joint'; | ||
import Texture2D from './Texture2D'; | ||
import { isPixelSource } from './Texture'; | ||
import BoundingBox from './math/BoundingBox'; | ||
@@ -247,8 +248,10 @@ import Matrix4 from './math/Matrix4'; | ||
})); | ||
texture.width = size; | ||
texture.height = size; | ||
if (!texture.pixels || texture.pixels.length !== size * size * 4) { | ||
texture.pixels = new Float32Array(size * size * 4); | ||
if (!isPixelSource(texture.source) || texture.source.data.length !== size * size * 4) { | ||
texture.source = { | ||
data: new Float32Array(size * size * 4), | ||
width: size, | ||
height: size | ||
}; | ||
} | ||
texture.pixels.set(skinMatrices); | ||
texture.source.data.set(skinMatrices); | ||
texture.dirty(); | ||
@@ -255,0 +258,0 @@ return texture; |
@@ -1,8 +0,20 @@ | ||
import Notifier from './core/Notifier'; | ||
import { GLEnum } from './core/type'; | ||
export declare type TextureImageSource = HTMLImageElement | HTMLCanvasElement | HTMLVideoElement; | ||
export declare type TexturePixelSource = Uint8Array | Float32Array; | ||
export declare type TexturePixelSource = { | ||
data: Uint8Array | Float32Array; | ||
width: number; | ||
height: number; | ||
depth?: number; | ||
}; | ||
export declare type TextureSource = TextureImageSource | TexturePixelSource; | ||
export declare function isPixelSource(source: TextureSource | undefined | null): source is TexturePixelSource; | ||
export declare function getPossiblelInternalFormat(format: number, type: number): number; | ||
export interface TextureOpts { | ||
export declare function getDefaultTextureFormatBySource(source?: TextureSource): number; | ||
export declare function getDefaultTypeBySource(source?: TextureSource): 5121 | 5126 | 5131; | ||
export interface TextureOpts<TSource = unknown> { | ||
/** | ||
* Source | ||
*/ | ||
source: TSource; | ||
/** | ||
* Texture width, readonly when the texture source is image | ||
@@ -99,10 +111,17 @@ */ | ||
} | ||
interface Texture extends Omit<TextureOpts, 'width' | 'height'> { | ||
interface Texture<TSource> extends Omit<TextureOpts, 'width' | 'height' | 'source'> { | ||
} | ||
declare abstract class Texture extends Notifier { | ||
protected _width: number; | ||
protected _height: number; | ||
declare abstract class Texture<TSource = unknown> { | ||
protected _width?: number; | ||
protected _height?: number; | ||
__dirty: boolean; | ||
textureType: string; | ||
private _source?; | ||
private _loadingPromise?; | ||
private _format?; | ||
private _type?; | ||
private _internalFormat?; | ||
constructor(opts?: Partial<TextureOpts>); | ||
get source(): TSource | undefined; | ||
set source(val: TSource | undefined); | ||
get width(): number; | ||
@@ -112,2 +131,10 @@ set width(value: number); | ||
set height(value: number); | ||
get type(): GLEnum; | ||
set type(type: GLEnum); | ||
get format(): GLEnum; | ||
set format(format: GLEnum); | ||
get internalFormat(): GLEnum; | ||
set internalFormat(internalFormat: GLEnum); | ||
protected _defaultFormat(): number; | ||
protected _defaultType(): number; | ||
/** | ||
@@ -124,2 +151,9 @@ * Mark texture is dirty and update in the next frame | ||
/** | ||
* Remove a promise that will be resolved if texture is ready. | ||
* Will return undefined if there is not any loading actions. | ||
* PENDING Should always return a promise? | ||
*/ | ||
checkReady(): Promise<void> | undefined; | ||
startLoading(doLoading: (resolve: () => void, reject: () => void) => void): Promise<void>; | ||
/** | ||
* Test if texture size is power of two | ||
@@ -126,0 +160,0 @@ * @return {boolean} |
@@ -6,33 +6,63 @@ /** | ||
import * as constants from './core/constants'; | ||
import Notifier from './core/Notifier'; | ||
import { isPowerOfTwo } from './math/util'; | ||
import { assign } from './core/util'; | ||
export function isPixelSource(source) { | ||
return !!(source && source.data); | ||
} | ||
// Compatible with WebGL1 for float type storage. | ||
// PENDING | ||
export function getPossiblelInternalFormat(format, type) { | ||
if (type === constants.HALF_FLOAT) { | ||
return format === constants.RGBA | ||
? constants.RGBA16F | ||
: format === constants.RGB | ||
? constants.RGB16F | ||
: format === constants.RG | ||
? constants.RG16F | ||
: constants.R16F; | ||
switch (type) { | ||
case constants.HALF_FLOAT: | ||
return format === constants.RGBA | ||
? constants.RGBA16F | ||
: format === constants.RGB | ||
? constants.RGB16F | ||
: format === constants.RG | ||
? constants.RG16F | ||
: constants.R16F; | ||
case constants.FLOAT: | ||
return format === constants.RGBA | ||
? constants.RGBA32F | ||
: format === constants.RGB | ||
? constants.RGB32F | ||
: format === constants.RG | ||
? constants.RG32F | ||
: constants.R32F; | ||
case constants.UNSIGNED_BYTE: | ||
return format === constants.RGBA | ||
? constants.RGBA8 | ||
: format === constants.RGB | ||
? constants.RGB8 | ||
: format === constants.RG | ||
? constants.RG8 | ||
: constants.R8; | ||
} | ||
else if (type === constants.FLOAT) { | ||
return format === constants.RGBA | ||
? constants.RGBA32F | ||
: format === constants.RGB | ||
? constants.RGB32F | ||
: format === constants.RG | ||
? constants.RG32F | ||
: constants.R32F; | ||
} | ||
return format; | ||
} | ||
class Texture extends Notifier { | ||
const formatMap = { | ||
1: constants.RED, | ||
2: constants.RG, | ||
3: constants.RGB, | ||
4: constants.RGBA | ||
}; | ||
export function getDefaultTextureFormatBySource(source) { | ||
if (isPixelSource(source)) { | ||
const channels = source.data.length / source.width / source.height / (source.depth || 1); | ||
return formatMap[channels] || constants.RGBA; | ||
} | ||
return constants.RGBA; | ||
} | ||
export function getDefaultTypeBySource(source) { | ||
if (isPixelSource(source)) { | ||
return source.data instanceof Float32Array | ||
? constants.FLOAT | ||
: source.data instanceof Uint16Array | ||
? constants.HALF_FLOAT | ||
: constants.UNSIGNED_BYTE; | ||
} | ||
return constants.UNSIGNED_BYTE; | ||
} | ||
class Texture { | ||
constructor(opts) { | ||
super(); | ||
this._width = 512; | ||
this._height = 512; | ||
this.__dirty = true; | ||
@@ -42,4 +72,13 @@ this.textureType = ''; | ||
} | ||
get source() { | ||
return this._source; | ||
} | ||
set source(val) { | ||
if (this._source !== val) { | ||
this._source = val; | ||
this.dirty(); | ||
} | ||
} | ||
get width() { | ||
return this._width; | ||
return this._width || 0; | ||
} | ||
@@ -50,3 +89,3 @@ set width(value) { | ||
get height() { | ||
return this._height; | ||
return this._height || 0; | ||
} | ||
@@ -56,2 +95,26 @@ set height(value) { | ||
} | ||
get type() { | ||
return this._type || this._defaultType(); | ||
} | ||
set type(type) { | ||
this._type = type; | ||
} | ||
get format() { | ||
return this._format || this._defaultFormat(); | ||
} | ||
set format(format) { | ||
this._format = format; | ||
} | ||
get internalFormat() { | ||
return this._internalFormat || getPossiblelInternalFormat(this.format, this.type); | ||
} | ||
set internalFormat(internalFormat) { | ||
this._internalFormat = internalFormat; | ||
} | ||
_defaultFormat() { | ||
return constants.RGBA; | ||
} | ||
_defaultType() { | ||
return constants.UNSIGNED_BYTE; | ||
} | ||
/** | ||
@@ -75,2 +138,16 @@ * Mark texture is dirty and update in the next frame | ||
/** | ||
* Remove a promise that will be resolved if texture is ready. | ||
* Will return undefined if there is not any loading actions. | ||
* PENDING Should always return a promise? | ||
*/ | ||
checkReady() { | ||
return this.isRenderable() ? Promise.resolve() : this._loadingPromise; | ||
} | ||
startLoading(doLoading) { | ||
return (this._loadingPromise = new Promise((resolve, reject) => { | ||
doLoading(resolve, reject); | ||
})); | ||
} | ||
// TODO check ready | ||
/** | ||
* Test if texture size is power of two | ||
@@ -85,4 +162,2 @@ * @return {boolean} | ||
const proto = Texture.prototype; | ||
proto.type = constants.UNSIGNED_BYTE; | ||
proto.format = constants.RGBA; | ||
proto.wrapS = constants.REPEAT; | ||
@@ -89,0 +164,0 @@ proto.wrapT = constants.REPEAT; |
@@ -1,23 +0,5 @@ | ||
import Texture, { TextureImageSource, TextureOpts, TexturePixelSource } from './Texture'; | ||
export interface Texture2DData { | ||
image?: TextureImageSource; | ||
/** | ||
* Pixels data. Will be ignored if image is set. | ||
*/ | ||
pixels?: TexturePixelSource; | ||
import Texture, { TextureOpts, TextureSource } from './Texture'; | ||
export interface Texture2DOpts extends TextureOpts<TextureSource> { | ||
mipmaps?: TextureSource[]; | ||
} | ||
export interface Texture2DOpts extends TextureOpts, Texture2DData { | ||
/** | ||
* @example | ||
* [{ | ||
* image: mipmap0, | ||
* pixels: null | ||
* }, { | ||
* image: mipmap1, | ||
* pixels: null | ||
* }, ....] | ||
*/ | ||
mipmaps?: Texture2DData[]; | ||
convertToPOT?: boolean; | ||
} | ||
/** | ||
@@ -40,10 +22,6 @@ * @example | ||
*/ | ||
interface Texture2D extends Omit<Texture2DOpts, 'image'> { | ||
} | ||
declare class Texture2D extends Texture { | ||
declare class Texture2D extends Texture<TextureSource> { | ||
readonly textureType = "texture2D"; | ||
private _image?; | ||
mipmaps?: TextureSource[]; | ||
constructor(opts?: Partial<Texture2DOpts>); | ||
get image(): TextureImageSource | undefined; | ||
set image(val: TextureImageSource | undefined); | ||
get width(): number; | ||
@@ -53,5 +31,7 @@ set width(value: number); | ||
set height(value: number); | ||
protected _defaultFormat(): number; | ||
protected _defaultType(): 5121 | 5126 | 5131; | ||
isRenderable(): boolean; | ||
load(src: string, crossOrigin?: string): this; | ||
load(src: string, crossOrigin?: string): Promise<void>; | ||
} | ||
export default Texture2D; |
@@ -1,3 +0,20 @@ | ||
import Texture from './Texture'; | ||
import Texture, { getDefaultTextureFormatBySource, getDefaultTypeBySource } from './Texture'; | ||
import vendor from './core/vendor'; | ||
/** | ||
* @example | ||
* ... | ||
* const mat = new clay.Material({ | ||
* shader: clay.shader.library.get('clay.phong', 'diffuseMap') | ||
* }); | ||
* const diffuseMap = new clay.Texture2D(); | ||
* diffuseMap.load('assets/textures/diffuse.jpg'); | ||
* mat.set('diffuseMap', diffuseMap); | ||
* ... | ||
* diffuseMap.onload(function () { | ||
* // Wait for the diffuse texture loaded | ||
* animation.on('frame', function (frameTime) { | ||
* renderer.render(scene, camera); | ||
* }); | ||
* }); | ||
*/ | ||
class Texture2D extends Texture { | ||
@@ -8,48 +25,53 @@ constructor(opts) { | ||
} | ||
get image() { | ||
return this._image; | ||
} | ||
set image(val) { | ||
if (this._image !== val) { | ||
this._image = val; | ||
this.dirty(); | ||
} | ||
} | ||
get width() { | ||
if (this.image) { | ||
return this.image.width; | ||
const source = this.source; | ||
const mipmaps = this.mipmaps; | ||
if (source) { | ||
return source.width; | ||
} | ||
return this._width; | ||
else if (mipmaps && mipmaps[0]) { | ||
return mipmaps[0].width; | ||
} | ||
return this._width || 0; | ||
} | ||
set width(value) { | ||
if (this.image) { | ||
console.warn("Texture from image can't set width"); | ||
const oldWidth = this.width; | ||
if (this.source) { | ||
this.source.width = value; | ||
} | ||
else { | ||
if (this._width !== value) { | ||
this.dirty(); | ||
} | ||
this._width = value; | ||
} | ||
oldWidth !== value && this.dirty(); | ||
} | ||
get height() { | ||
if (this.image) { | ||
return this.image.height; | ||
const source = this.source; | ||
const mipmaps = this.mipmaps; | ||
if (source) { | ||
return source.height; | ||
} | ||
return this._height; | ||
else if (mipmaps && mipmaps[0]) { | ||
return mipmaps[0].height; | ||
} | ||
return this._height || 0; | ||
} | ||
set height(value) { | ||
if (this.image) { | ||
console.warn("Texture from image can't set height"); | ||
const oldHeight = this.height; | ||
if (this.source) { | ||
this.source.height = value; | ||
} | ||
else { | ||
if (this._height !== value) { | ||
this.dirty(); | ||
} | ||
this._height = value; | ||
} | ||
oldHeight !== value && this.dirty(); | ||
} | ||
_defaultFormat() { | ||
return getDefaultTextureFormatBySource(this.source); | ||
} | ||
_defaultType() { | ||
return getDefaultTypeBySource(this.source); | ||
} | ||
isRenderable() { | ||
if (this.image) { | ||
return this.image.width > 0 && this.image.height > 0; | ||
if (this.source) { | ||
return this.source.width > 0 && this.source.height > 0; | ||
} | ||
@@ -61,20 +83,13 @@ else { | ||
load(src, crossOrigin) { | ||
const image = vendor.createImage(); | ||
if (crossOrigin) { | ||
image.crossOrigin = crossOrigin; | ||
} | ||
image.onload = () => { | ||
this.dirty(); | ||
this.trigger('load', this); | ||
}; | ||
image.onerror = () => { | ||
this.trigger('error', this); | ||
}; | ||
image.src = src; | ||
this.image = image; | ||
return this; | ||
return this.startLoading((resolve, reject) => { | ||
this.source = vendor.loadImage(src, crossOrigin, () => { | ||
this.dirty(); | ||
resolve(); | ||
}, (e) => { | ||
reject(); | ||
}); | ||
}); | ||
} | ||
} | ||
Texture2D.prototype.convertToPOT = false; | ||
export default Texture2D; | ||
//# sourceMappingURL=Texture2D.js.map |
@@ -1,19 +0,8 @@ | ||
import Texture, { TextureImageSource, TextureOpts, TexturePixelSource } from './Texture'; | ||
import Texture, { TextureOpts, TextureSource } from './Texture'; | ||
export declare const cubeTargets: readonly ["px", "nx", "py", "ny", "pz", "nz"]; | ||
export declare type CubeTarget = 'px' | 'nx' | 'py' | 'ny' | 'pz' | 'nz'; | ||
export interface TextureCubeData { | ||
image?: Record<CubeTarget, TextureImageSource>; | ||
/** | ||
* Pixels data. Will be ignored if image is set. | ||
*/ | ||
pixels?: Record<CubeTarget, TexturePixelSource>; | ||
export declare type TextureCubeSource = Record<CubeTarget, TextureSource | undefined>; | ||
export interface TextureCubeOpts extends TextureOpts<TextureCubeSource> { | ||
mipmaps?: TextureCubeSource[]; | ||
} | ||
export interface TextureCubeOpts extends TextureOpts, TextureCubeData { | ||
/** | ||
* @type {Array.<Object>} | ||
*/ | ||
mipmaps?: TextureCubeData[]; | ||
} | ||
interface TextureCube extends TextureCubeOpts { | ||
} | ||
/** | ||
@@ -46,4 +35,5 @@ * @constructor clay.TextureCube | ||
*/ | ||
declare class TextureCube extends Texture { | ||
declare class TextureCube extends Texture<TextureCubeSource> { | ||
readonly textureType = "textureCube"; | ||
mipmaps?: TextureCubeSource[]; | ||
constructor(opts?: Partial<TextureCubeOpts>); | ||
@@ -54,6 +44,8 @@ get width(): number; | ||
set height(value: number); | ||
protected _defaultFormat(): number; | ||
protected _defaultType(): 5121 | 5126 | 5131; | ||
isPowerOfTwo(): boolean; | ||
isRenderable(): boolean; | ||
load(imageList: Record<CubeTarget, string>, crossOrigin?: string): this; | ||
load(srcList: Record<CubeTarget, string>, crossOrigin?: string): Promise<void>; | ||
} | ||
export default TextureCube; |
@@ -1,2 +0,2 @@ | ||
import Texture from './Texture'; | ||
import Texture, { getDefaultTextureFormatBySource, getDefaultTypeBySource } from './Texture'; | ||
import * as mathUtil from './math/util'; | ||
@@ -40,43 +40,59 @@ import vendor from './core/vendor'; | ||
get width() { | ||
const images = this.image; | ||
if (images && images.px) { | ||
return images.px.width; | ||
const source = this.source; | ||
const mipmaps = this.mipmaps; | ||
if (source && source.px) { | ||
return source.px.width; | ||
} | ||
return this._width; | ||
else if (mipmaps && mipmaps[0] && mipmaps[0].px) { | ||
return mipmaps[0].px.width; | ||
} | ||
return this._width || 0; | ||
} | ||
set width(value) { | ||
const images = this.image; | ||
if (images && images.px) { | ||
console.warn("Texture from image can't set width"); | ||
const oldWidth = this.width; | ||
const source = this.source; | ||
if (source && source.px) { | ||
keys(source).forEach((target) => { | ||
source[target] && (source[target].width = value); | ||
}); | ||
} | ||
else { | ||
if (this._width !== value) { | ||
this.dirty(); | ||
} | ||
this._width = value; | ||
} | ||
oldWidth !== value && this.dirty(); | ||
} | ||
get height() { | ||
const images = this.image; | ||
if (images && images.px) { | ||
return images.px.height; | ||
const source = this.source; | ||
const mipmaps = this.mipmaps; | ||
if (source && source.px) { | ||
return source.px.height; | ||
} | ||
return this._height; | ||
else if (mipmaps && mipmaps[0] && mipmaps[0].px) { | ||
return mipmaps[0].px.height; | ||
} | ||
return this._height || 0; | ||
} | ||
set height(value) { | ||
const images = this.image; | ||
if (images && images.px) { | ||
console.warn("Texture from image can't set height"); | ||
const oldHeight = this.height; | ||
const source = this.source; | ||
if (source && source.px) { | ||
keys(source).forEach((target) => { | ||
source[target] && (source[target].height = value); | ||
}); | ||
} | ||
else { | ||
if (this._height !== value) { | ||
this.dirty(); | ||
} | ||
this._height = value; | ||
} | ||
oldHeight !== value && this.dirty(); | ||
} | ||
_defaultFormat() { | ||
return getDefaultTextureFormatBySource(this.source && this.source.px); | ||
} | ||
_defaultType() { | ||
return getDefaultTypeBySource(this.source && this.source.px); | ||
} | ||
// Overwrite the isPowerOfTwo method | ||
isPowerOfTwo() { | ||
if (this.image && this.image.px) { | ||
return isPowerOfTwo(this.image.px.width) && isPowerOfTwo(this.image.px.height); | ||
if (this.source && this.source.px) { | ||
return isPowerOfTwo(this.source.px.width) && isPowerOfTwo(this.source.px.height); | ||
} | ||
@@ -88,9 +104,9 @@ else { | ||
isRenderable() { | ||
if (this.image && this.image.px) { | ||
return (isImageRenderable(this.image.px) && | ||
isImageRenderable(this.image.nx) && | ||
isImageRenderable(this.image.py) && | ||
isImageRenderable(this.image.ny) && | ||
isImageRenderable(this.image.pz) && | ||
isImageRenderable(this.image.nz)); | ||
if (this.source && this.source.px) { | ||
return (isImageRenderable(this.source.px) && | ||
isImageRenderable(this.source.nx) && | ||
isImageRenderable(this.source.py) && | ||
isImageRenderable(this.source.ny) && | ||
isImageRenderable(this.source.pz) && | ||
isImageRenderable(this.source.nz)); | ||
} | ||
@@ -101,32 +117,23 @@ else { | ||
} | ||
load(imageList, crossOrigin) { | ||
let loading = 0; | ||
this.image = {}; | ||
keys(imageList).forEach((target) => { | ||
const src = imageList[target]; | ||
const image = vendor.createImage(); | ||
if (crossOrigin) { | ||
image.crossOrigin = crossOrigin; | ||
} | ||
image.onload = () => { | ||
loading--; | ||
if (loading === 0) { | ||
load(srcList, crossOrigin) { | ||
return this.startLoading((resolve, reject) => { | ||
this.source = {}; | ||
let loading = 0; | ||
const done = () => { | ||
if (--loading === 0) { | ||
this.dirty(); | ||
this.trigger('success', this); | ||
resolve(); | ||
} | ||
}; | ||
image.onerror = function () { | ||
loading--; | ||
}; | ||
loading++; | ||
image.src = src; | ||
this.image[target] = image; | ||
keys(srcList).forEach((target) => { | ||
this.source[target] = vendor.loadImage(srcList[target], crossOrigin, done, done); | ||
loading++; | ||
}); | ||
}); | ||
return this; | ||
} | ||
} | ||
function isImageRenderable(image) { | ||
return image.width > 0 && image.height > 0; | ||
return image != null && image.width > 0 && image.height > 0; | ||
} | ||
export default TextureCube; | ||
//# sourceMappingURL=TextureCube.js.map |
@@ -5,3 +5,3 @@ // Cubemap prefilter utility | ||
import Texture2D from '../Texture2D'; | ||
import TextureCube from '../TextureCube'; | ||
import TextureCube, { cubeTargets } from '../TextureCube'; | ||
import FrameBuffer from '../FrameBuffer'; | ||
@@ -21,3 +21,2 @@ import FullscreenQuadPass from '../composite/Pass'; | ||
import CubeGeometry from '../geometry/Cube'; | ||
const targets = ['px', 'nx', 'py', 'ny', 'pz', 'nz']; | ||
// TODO Downsample | ||
@@ -46,3 +45,2 @@ // TODO ggx | ||
}); | ||
prefilteredCubeMap.mipmaps = []; | ||
if (!prefilteredCubeMap.isPowerOfTwo()) { | ||
@@ -86,18 +84,7 @@ console.warn('Width and height must be power of two to enable mipmap.'); | ||
} | ||
const renderTargetTmp = new Texture2D({ | ||
width, | ||
height, | ||
type: textureType | ||
}); | ||
const frameBuffer = new FrameBuffer({ | ||
depthBuffer: false | ||
}); | ||
const ArrayCtor = textureType === constants.UNSIGNED_BYTE ? Uint8Array : Float32Array; | ||
// const container = document.createElement('div'); | ||
// document.body.appendChild(container); | ||
// container.style.cssText = 'position: absolute; left: 0; top: 0;'; | ||
frameBuffer.autoGenerateMipmap = false; | ||
for (let i = 0; i < mipmapNum; i++) { | ||
prefilteredCubeMap.mipmaps[i] = { | ||
pixels: {} | ||
}; | ||
prefilterMaterial.set('roughness', i / (mipmapNum - 1)); | ||
@@ -109,32 +96,13 @@ // Tweak fov. TODO It will cause leaking on the edge in the latest chrome | ||
const fov = 90; | ||
for (let j = 0; j < targets.length; j++) { | ||
const pixels = new ArrayCtor(renderTargetTmp.width * renderTargetTmp.height * 4); | ||
frameBuffer.attach(renderTargetTmp); | ||
const camera = envMapPass.getCamera(targets[j]); | ||
for (let j = 0; j < cubeTargets.length; j++) { | ||
frameBuffer.clearTextures(); | ||
frameBuffer.mipmapLevel = i; | ||
frameBuffer.attach(prefilteredCubeMap, constants.COLOR_ATTACHMENT0, constants.TEXTURE_CUBE_MAP_POSITIVE_X + j); | ||
const camera = envMapPass.getCamera(cubeTargets[j]); | ||
camera.fov = fov; | ||
renderer.render(dummyScene, camera, frameBuffer); | ||
renderer.gl.readPixels(0, 0, renderTargetTmp.width, renderTargetTmp.height, constants.RGBA, textureType, pixels); | ||
// const canvas = document.createElement('canvas'); | ||
// const ctx = canvas.getContext('2d')!; | ||
// canvas.width = renderTargetTmp.width; | ||
// canvas.height = renderTargetTmp.height; | ||
// const imageData = ctx.createImageData(renderTargetTmp.width, renderTargetTmp.height); | ||
// for (let k = 0; k < pixels.length; k += 4) { | ||
// const a = pixels[k + 3] / 255; | ||
// const range = 8.12; | ||
// imageData.data[k] = pixels[k] * a * range; | ||
// imageData.data[k + 1] = pixels[k + 1] * a * range; | ||
// imageData.data[k + 2] = pixels[k + 2] * a * range; | ||
// imageData.data[k + 3] = 255; | ||
// } | ||
// ctx.putImageData(imageData, 0, 0); | ||
// container.appendChild(canvas); | ||
prefilteredCubeMap.mipmaps[i].pixels[targets[j]] = pixels; | ||
} | ||
renderTargetTmp.width /= 2; | ||
renderTargetTmp.height /= 2; | ||
renderTargetTmp.dirty(); | ||
} | ||
renderer.disposeFrameBuffer(frameBuffer); | ||
renderer.disposeTexture(renderTargetTmp); | ||
// renderer.disposeTexture(renderTargetTmp); | ||
renderer.disposeGeometry(mesh.geometry); | ||
@@ -174,13 +142,2 @@ if (newCreatedCubemap) { | ||
quadPass.render(renderer, framebuffer); | ||
// FIXME Only chrome and firefox can readPixels with float type. | ||
// framebuffer.bind(renderer); | ||
// const pixels = new Float32Array(512 * 256 * 4); | ||
// renderer.gl.readPixels( | ||
// 0, 0, texture.width, texture.height, | ||
// Texture.RGBA, Texture.FLOAT, pixels | ||
// ); | ||
// texture.pixels = pixels; | ||
// texture.flipY = false; | ||
// texture.dirty(); | ||
// framebuffer.unbind(renderer); | ||
renderer.disposeFrameBuffer(framebuffer); | ||
@@ -196,4 +153,2 @@ return texture; | ||
const normalDistribution = new Texture2D({ | ||
width: roughnessLevels, | ||
height: sampleSize, | ||
type: constants.FLOAT, | ||
@@ -240,5 +195,9 @@ minFilter: constants.NEAREST, | ||
} | ||
normalDistribution.pixels = pixels; | ||
normalDistribution.source = { | ||
data: pixels, | ||
width: roughnessLevels, | ||
height: sampleSize | ||
}; | ||
return normalDistribution; | ||
} | ||
//# sourceMappingURL=cubemap.js.map |
@@ -112,6 +112,12 @@ import Texture2D from '../Texture2D'; | ||
} | ||
textures[f].pixels = mipmaps[0]; | ||
textures[f].source = { | ||
data: mipmaps[0], | ||
width, | ||
height | ||
}; | ||
if (hasMipmap) { | ||
textures[f].mipmaps = mipmaps.map((mipmap) => ({ | ||
pixels: mipmap | ||
data: mipmap, | ||
width: width * 0.5, | ||
height: height * 0.5 | ||
})); | ||
@@ -123,6 +129,4 @@ } | ||
if (out) { | ||
out.width = textures[0].width; | ||
out.height = textures[0].height; | ||
out.format = textures[0].format; | ||
out.pixels = textures[0].pixels; | ||
out.source = textures[0].source; | ||
out.mipmaps = textures[0].mipmaps; | ||
@@ -129,0 +133,0 @@ } |
@@ -157,5 +157,7 @@ import Texture2D from '../Texture2D'; | ||
} | ||
texture.width = width; | ||
texture.height = height; | ||
texture.pixels = pixels; | ||
texture.source = { | ||
data: pixels, | ||
width, | ||
height | ||
}; | ||
// HALF_FLOAT can't use Float32Array | ||
@@ -162,0 +164,0 @@ texture.type = constants.FLOAT; |
@@ -95,3 +95,3 @@ // KTX loader | ||
mipmaps.push({ | ||
pixels: byteArray, | ||
data: byteArray, | ||
width: width, | ||
@@ -109,4 +109,2 @@ height: height | ||
new Texture2D({ | ||
width: pixelWidth, | ||
height: pixelHeight, | ||
format: glInternalFormat | ||
@@ -118,7 +116,9 @@ }); | ||
} | ||
else { | ||
out.pixels = mipmaps[0].pixels; | ||
} | ||
out.source = { | ||
data: mipmaps[0].data, | ||
width: pixelWidth, | ||
height: pixelHeight | ||
}; | ||
return out; | ||
} | ||
//# sourceMappingURL=ktx.js.map |
@@ -128,3 +128,3 @@ import FrameBuffer from '../FrameBuffer'; | ||
else { | ||
size = envMap.image && envMap.image.px ? envMap.image.px.width : envMap.width; | ||
size = envMap.source && envMap.source.px ? envMap.source.px.width : envMap.width; | ||
skybox = new Skybox({ | ||
@@ -131,0 +131,0 @@ environmentMap: envMap |
@@ -32,7 +32,10 @@ import Texture2D from '../Texture2D'; | ||
}); | ||
fetchTexture(path, (data) => { | ||
hdr.parseRGBE(data, texture, option.exposure); | ||
texture.dirty(); | ||
onload && onload(texture); | ||
}, onerror); | ||
texture.startLoading((finished) => { | ||
fetchTexture(path, (data) => { | ||
hdr.parseRGBE(data, texture, option.exposure); | ||
texture.dirty(); | ||
finished(); | ||
onload && onload(texture); | ||
}, onerror); | ||
}); | ||
return texture; | ||
@@ -45,14 +48,14 @@ } | ||
}); | ||
fetchTexture(path, (data) => { | ||
dds.parse(data, texture); | ||
texture.dirty(); | ||
onload && onload(texture); | ||
}, onerror); | ||
texture.startLoading((finished) => { | ||
fetchTexture(path, (data) => { | ||
dds.parse(data, texture); | ||
texture.dirty(); | ||
finished(); | ||
onload && onload(texture); | ||
}, onerror); | ||
}); | ||
} | ||
else { | ||
texture = new Texture2D(); | ||
texture | ||
.load(path) | ||
.onload(onload) | ||
.onerror(onerror); | ||
texture.load(path).then(() => onload && onload(texture), onerror); | ||
} | ||
@@ -225,3 +228,3 @@ return texture; | ||
const texture = new Texture2D({ | ||
image: canvas, | ||
source: canvas, | ||
anisotropic: 8 | ||
@@ -238,5 +241,5 @@ }); | ||
return new Texture2D({ | ||
image: vendor.createBlankCanvas(color) | ||
source: vendor.createBlankCanvas(color) | ||
}); | ||
} | ||
//# sourceMappingURL=texture.js.map |
{ | ||
"name": "claygl-next", | ||
"version": "2.0.0-alpha.10", | ||
"version": "2.0.0-alpha.11", | ||
"description": "A 3D graphic library", | ||
@@ -28,3 +28,4 @@ "keywords": [ | ||
"watch:lib": "npx tsc --watch", | ||
"dev": "vite ./ --config example/vite.config.js" | ||
"dev": "vite ./ --config example/vite.config.js", | ||
"check:example": "npx tsc --noEmit -p example/tsconfig.json" | ||
}, | ||
@@ -31,0 +32,0 @@ "repository": { |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
6983511
559
105564