Skip to content
Snippets Groups Projects
Commit 8c23b31c authored by Alexander Rose's avatar Alexander Rose
Browse files

wip

parent 40124be6
No related branches found
No related tags found
No related merge requests found
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { Context } from './context'
function addLineNumbers(source: string) {
const lines = source.split('\n')
for (let i = 0; i < lines.length; ++i) {
lines[i] = (i + 1) + ': ' + lines[i]
}
return lines.join('\n')
}
type ShaderType = 'vert' | 'frag'
function createShader(gl: WebGLRenderingContext, type: ShaderType, source: string) {
const shader = gl.createShader(type === 'vert' ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER)
if (shader === null) {
throw new Error(`Error creating ${type} shader`)
}
gl.shaderSource(shader, source)
gl.compileShader(shader)
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) === false) {
console.warn(`'${type}' shader info log '${gl.getShaderInfoLog(shader)}'\n${addLineNumbers(source)}`)
throw new Error(`Error compiling ${type} shader`)
}
return shader
}
export function getShader(ctx: Context, type: ShaderType, source: string) {
let shaderRef = ctx.shaderCache.get(source)
if (!shaderRef) {
shaderRef = { usageCount: 0, value: createShader(ctx.gl, type, source) }
ctx.shaderCache.set(source, shaderRef)
}
shaderRef.usageCount += 1
return {
free: () => {
if (shaderRef) {
shaderRef.usageCount -= 1
shaderRef = undefined
}
},
value: shaderRef.value
}
}
\ No newline at end of file
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
// import { Context } from './context'
export interface Texture {
load: (image: ImageData) => void
bind: (id: TextureId) => void
}
export type TextureId = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15
export type TextureTarget = 'TEXTURE0' | 'TEXTURE1' | 'TEXTURE2' | 'TEXTURE3' | 'TEXTURE4' | 'TEXTURE5' | 'TEXTURE6' | 'TEXTURE7' | 'TEXTURE8' | 'TEXTURE9' | 'TEXTURE10' | 'TEXTURE11' | 'TEXTURE12' | 'TEXTURE13' | 'TEXTURE14' | 'TEXTURE15'
export type TextureDefs = { [k: string]: '' }
export type TextureUniforms<T extends TextureDefs> = { [k in keyof T]: 't2' }
export type TextureValues<T extends TextureDefs> = { [k in keyof T]: ImageData }
export type Textures<T extends TextureDefs> = { [k in keyof T]: Texture }
export function createTexture(gl: WebGLRenderingContext): Texture {
const texture = gl.createTexture()
if (texture === null) {
throw new Error('Could not create WebGL texture')
}
return {
load: (image: ImageData) => {
gl.bindTexture(gl.TEXTURE_2D, texture)
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true)
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
gl.bindTexture(gl.TEXTURE_2D, null)
},
bind: (id: TextureId) => {
gl.activeTexture(gl[`TEXTURE${id}` as TextureTarget])
gl.bindTexture(gl.TEXTURE_2D, texture)
}
}
}
export function createTextures<T extends TextureDefs>(gl: WebGLRenderingContext, props: T, state: TextureValues<T>) {
const textures: Partial<Textures<T>> = {}
Object.keys(props).forEach(k => {
const texture = createTexture(gl)
texture.load(state[k])
textures[k] = texture
})
return textures as Textures<T>
}
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { Mat3, Mat4, Vec2, Vec3, Vec4 } from 'mol-math/linear-algebra'
export type UniformKindValue = {
'f': number
'i': number
'v2': Vec2
'v3': Vec3
'v4': Vec4
'm3': Mat3
'm4': Mat4
't2': number
}
export type UniformKind = keyof UniformKindValue
export type UniformDefs = { [k: string]: UniformKind }
export type UniformValues<T extends UniformDefs> = { [K in keyof T]: UniformKindValue[T[K]] }
export type UniformSetters<T extends UniformDefs> = { [K in keyof T]: (value: UniformKindValue[T[K]]) => void }
export function createUniformSetter<K extends UniformKind, V = UniformKindValue[K]>(gl: WebGLRenderingContext, program: WebGLProgram, name: string, kind: K): (value: V) => void {
const location = gl.getUniformLocation(program, name)
switch (kind) {
case 'f' as K: return (value: V) => gl.uniform1f(location, value as any as number)
case 'i': case 't2': return (value: V) => gl.uniform1i(location, value as any as number)
case 'v2': return (value: V) => gl.uniform2fv(location, value as any as Vec2)
case 'v3': return (value: V) => gl.uniform3fv(location, value as any as Vec3)
case 'v4': return (value: V) => gl.uniform4fv(location, value as any as Vec4)
case 'm3': return (value: V) => gl.uniformMatrix3fv(location, false, value as any as Mat3)
case 'm4': return (value: V) => gl.uniformMatrix4fv(location, false, value as any as Mat4)
}
throw new Error('Should never happen')
}
export function getUniformSetters<T extends UniformDefs, K = keyof T>(gl: WebGLRenderingContext, program: WebGLProgram, uniforms: T) {
const setters: Partial<UniformSetters<T>> = {}
Object.keys(uniforms).forEach(k => {
setters[k] = createUniformSetter(gl, program, k, uniforms[k])
})
return setters as UniformSetters<T>
}
\ No newline at end of file
...@@ -24,6 +24,51 @@ export function arrayEqual<T>(arr1: T[], arr2: T[]) { ...@@ -24,6 +24,51 @@ export function arrayEqual<T>(arr1: T[], arr2: T[]) {
return true return true
} }
export function deepEqual(a: any, b: any) {
// from https://github.com/epoberezkin/fast-deep-equal MIT
if (a === b) return true;
const arrA = Array.isArray(a)
const arrB = Array.isArray(b)
if (arrA && arrB) {
if (a.length !== b.length) return false
for (let i = 0; i < a.length; i++) {
if (!deepEqual(a[i], b[i])) return false
}
return true
}
if (arrA !== arrB) return false
if (a && b && typeof a === 'object' && typeof b === 'object') {
const keys = Object.keys(a)
if (keys.length !== Object.keys(b).length) return false;
const dateA = a instanceof Date
const dateB = b instanceof Date
if (dateA && dateB) return a.getTime() === b.getTime()
if (dateA !== dateB) return false
const regexpA = a instanceof RegExp
const regexpB = b instanceof RegExp
if (regexpA && regexpB) return a.toString() === b.toString()
if (regexpA !== regexpB) return false
for (let i = 0; i < keys.length; i++) {
if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false
}
for (let i = 0; i < keys.length; i++) {
if (!deepEqual(a[keys[i]], b[keys[i]])) return false
}
return true
}
return false
}
export function defaults(value: any, defaultValue: any) { export function defaults(value: any, defaultValue: any) {
return value !== undefined ? value : defaultValue return value !== undefined ? value : defaultValue
} }
\ No newline at end of file
...@@ -22,6 +22,7 @@ interface Viewer { ...@@ -22,6 +22,7 @@ interface Viewer {
add: (repr: StructureRepresentation) => void add: (repr: StructureRepresentation) => void
remove: (repr: StructureRepresentation) => void remove: (repr: StructureRepresentation) => void
update: () => void
clear: () => void clear: () => void
draw: (force?: boolean) => void draw: (force?: boolean) => void
...@@ -119,6 +120,7 @@ namespace Viewer { ...@@ -119,6 +120,7 @@ namespace Viewer {
const renderObjectSet = reprMap.get(repr) const renderObjectSet = reprMap.get(repr)
if (renderObjectSet) renderObjectSet.forEach(o => renderer.remove(o)) if (renderObjectSet) renderObjectSet.forEach(o => renderer.remove(o))
}, },
update: () => renderer.update(),
clear: () => { clear: () => {
reprMap.clear() reprMap.clear()
renderer.clear() renderer.clear()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment