Parcourir la source

refactored texture to allowdifferent formats and types

Alexander Rose il y a 6 ans
Parent
commit
faffcda85a
2 fichiers modifiés avec 65 ajouts et 21 suppressions
  1. 5 4
      src/mol-gl/renderable/schema.ts
  2. 60 17
      src/mol-gl/webgl/texture.ts

+ 5 - 4
src/mol-gl/renderable/schema.ts

@@ -10,6 +10,7 @@ import { UniformKind } from '../webgl/uniform';
 import { DefineKind } from '../shader-code';
 import { Vec2, Vec3, Vec4, Mat3, Mat4 } from 'mol-math/linear-algebra';
 import { TextureImage } from './util';
+import { TextureValues, TextureType, TextureFormat } from '../webgl/texture';
 
 export type ValueKindType = {
     'number': number
@@ -60,9 +61,9 @@ export function UniformSpec<K extends UniformKind>(kind: K): UniformSpec<K> {
     return { type: 'uniform', kind }
 }
 
-export type TextureSpec = { type: 'texture', kind: 'image' }
-export function TextureSpec(): TextureSpec {
-    return { type: 'texture', kind: 'image' }
+export type TextureSpec = { type: 'texture', kind: 'image', format: TextureFormat, dataType: TextureType }
+export function TextureSpec(format: TextureFormat, dataType: TextureType): TextureSpec {
+    return { type: 'texture', kind: 'image', format, dataType }
 }
 
 export type ElementsSpec<K extends ElementsKind> = { type: 'elements', kind: K }
@@ -120,7 +121,7 @@ export const BaseSchema = {
     uColorTexSize: UniformSpec('v2'),
     uColor: UniformSpec('v3'),
 
-    tColor: TextureSpec(),
+    tColor: TextureSpec('rgb', 'ubyte'),
 
     drawCount: ValueSpec('number'),
     instanceCount: ValueSpec('number'),

+ 60 - 17
src/mol-gl/webgl/texture.ts

@@ -11,11 +11,39 @@ import { RenderableSchema } from '../renderable/schema';
 import { idFactory } from 'mol-util/id-factory';
 
 const getNextTextureId = idFactory()
+
+export type TextureFormat = 'rgb' | 'rgba'
+export type TextureType = 'ubyte' | 'uint'
+
+export function getFormat(ctx: Context, format: TextureFormat) {
+    const { gl } = ctx
+    switch (format) {
+        case 'rgb': return gl.RGB
+        case 'rgba': return gl.RGBA
+    }
+}
+
+export function getType(ctx: Context, type: TextureType) {
+    const { gl } = ctx
+    switch (type) {
+        case 'ubyte': return gl.UNSIGNED_BYTE
+        case 'uint': return gl.UNSIGNED_INT
+    }
+}
+
 export interface Texture {
     readonly id: number
+    readonly texture: WebGLTexture
+    readonly format: number
+    readonly type: number
+
+    readonly width: number
+    readonly height: number
+
     load: (image: TextureImage) => void
     bind: (id: TextureId) => void
     unbind: (id: TextureId) => void
+    setSize: (width: number, height: number) => void
     destroy: () => void
 }
 
@@ -24,7 +52,7 @@ export type TextureId = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 1
 export type TextureValues = { [k: string]: ValueCell<TextureImage> }
 export type Textures = { [k: string]: Texture }
 
-export function createTexture(ctx: Context): Texture {
+export function createTexture(ctx: Context, _format: TextureFormat, _type: TextureType): Texture {
     const id = getNextTextureId()
     const { gl } = ctx
     const texture = gl.createTexture()
@@ -32,39 +60,54 @@ export function createTexture(ctx: Context): Texture {
         throw new Error('Could not create WebGL texture')
     }
 
-    const _textureType = gl.TEXTURE_2D
-    const _magFilter = gl.NEAREST
-    const _minFilter = gl.NEAREST
-    const _format = gl.RGB
-    const _arrayType = gl.UNSIGNED_BYTE
+    const magFilter = gl.NEAREST
+    const minFilter = gl.NEAREST
+    const format = getFormat(ctx, _format)
+    const type = getType(ctx, _type)
+
+    let _width = 0
+    let _height = 0
 
     let destroyed = false
     ctx.textureCount += 1
 
     return {
         id,
+        texture,
+        format,
+        type,
+
+        get width () { return _width },
+        get height () { return _height },
+
         load: (image: TextureImage) => {
             const { array, width, height } = image
-            gl.bindTexture(_textureType, texture)
+            gl.bindTexture(gl.TEXTURE_2D, texture)
             // unpack alignment of 1 since we use textures only for data
             gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
-            gl.texImage2D(_textureType, 0, _format, width, height, 0, _format, _arrayType, array)
-            gl.texParameteri(_textureType, gl.TEXTURE_MAG_FILTER, _magFilter)
-            gl.texParameteri(_textureType, gl.TEXTURE_MIN_FILTER, _minFilter)
+            gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, type, array)
+            _width = width
+            _height = height
+            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter)
+            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter)
             // clamp-to-edge needed for non-power-of-two textures
-            gl.texParameteri(_textureType, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
-            gl.texParameteri(_textureType, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
-            gl.bindTexture(_textureType, null)
+            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+            gl.bindTexture(gl.TEXTURE_2D, null)
         },
         bind: (id: TextureId) => {
             gl.activeTexture(gl.TEXTURE0 + id)
-            gl.bindTexture(_textureType, texture)
+            gl.bindTexture(gl.TEXTURE_2D, texture)
         },
         unbind: (id: TextureId) => {
             gl.activeTexture(gl.TEXTURE0 + id)
-            gl.bindTexture(_textureType, null)
+            gl.bindTexture(gl.TEXTURE_2D, null)
+        },
+        setSize: (width: number, height: number) => {
+            gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, type, null)
+            _width = width
+            _height = height
         },
-
         destroy: () => {
             if (destroyed) return
             gl.deleteTexture(texture)
@@ -79,7 +122,7 @@ export function createTextures(ctx: Context, schema: RenderableSchema, values: T
     Object.keys(schema).forEach((k, i) => {
         const spec = schema[k]
         if (spec.type === 'texture') {
-            const texture = createTexture(ctx)
+            const texture = createTexture(ctx, spec.format, spec.dataType)
             texture.load(values[k].ref.value)
             textures[k] = texture
         }