cables_dev/cables/src/core/cgl/cgl_shader_uniform.js
import CgUniform from "../cg/cg_uniform.js";
import { Port } from "../core_port.js";
/**
* Shader uniforms
*
* types:
* <pre>
* f - float
* 2f - vec2
* 3f - vec3
* 4f - vec4
* i - integer
* t - texture
* m4 - mat4, 4x4 float matrix
* f[] - array of floats
* 2f[] - array of float vec2
* 3f[] - array of float vec3
* 4f[] - array of float vec4
* </pre>
*
* @namespace external:CGL
* @class
* @param {Shader} shader
* @param {String} [type=f]
* @param {String} name
* @param {Number|Port} value can be a Number,Matrix or Port
* @example
* // bind float uniform called myfloat and initialize with value 1.0
* const unir=new CGL.Uniform(shader,'f','myfloat',1.0);
* unir.setValue(1.0);
*
* // bind float uniform called myfloat and automatically set it to input port value
* const myPort=op.inFloat("input");
* const pv=new CGL.Uniform(shader,'f','myfloat',myPort);
*
*/
// export const Uniform(__shader, __type, __name, _value, _port2, _port3, _port4, _structUniformName, _structName, _propertyName)
class Uniform extends CgUniform
{
constructor(__shader, __type, __name, _value, _port2, _port3, _port4, _structUniformName, _structName, _propertyName)
{
super(__shader, __type, __name, _value, _port2, _port3, _port4, _structUniformName, _structName, _propertyName);
this._loc = -1;
this._cgl = __shader._cgl;
}
get name()
{
return this._name;
}
copy(newShader)
{
const uni = new Uniform(newShader, this._type, this._name, this._value, this._port2, this._port3, this._port4, this._structUniformName, this._structName, this._propertyName);
uni.shaderType = this.shaderType;
return uni;
}
/**
* returns type as glsl type string. e.g. 'f' returns 'float'
* @function getGlslTypeString
* @memberof Uniform
* @instance
* @return {string} type as string
*/
getGlslTypeString()
{
return Uniform.glslTypeString(this._type);
}
_isValidLoc()
{
return this._loc != -1;// && this._loc != null;
}
resetLoc()
{
this._loc = -1;
this.needsUpdate = true;
}
bindTextures() {}
getLoc()
{
return this._loc;
}
updateFromPort4f()
{
this._value[0] = this._port.get();
this._value[1] = this._port2.get();
this._value[2] = this._port3.get();
this._value[3] = this._port4.get();
this.setValue(this._value);
}
updateFromPort3f()
{
this._value[0] = this._port.get();
this._value[1] = this._port2.get();
this._value[2] = this._port3.get();
this.setValue(this._value);
}
updateFromPort2f()
{
this._value[0] = this._port.get();
this._value[1] = this._port2.get();
this.setValue(this._value);
}
updateFromPort()
{
this.setValue(this._port.get());
}
updateValueF()
{
if (!this._isValidLoc()) this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
else this.needsUpdate = false;
this._shader.getCgl().gl.uniform1f(this._loc, this._value);
this._cgl.profileData.profileUniformCount++;
}
setValueF(v)
{
if (v != this._value)
{
this.needsUpdate = true;
this._value = v;
}
}
updateValueI()
{
if (!this._isValidLoc()) this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
else this.needsUpdate = false;
this._shader.getCgl().gl.uniform1i(this._loc, this._value);
this._cgl.profileData.profileUniformCount++;
}
updateValue2I()
{
if (!this._value) return;
if (!this._isValidLoc())
{
this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
this._cgl.profileData.profileShaderGetUniform++;
this._cgl.profileData.profileShaderGetUniformName = this._name;
}
this._shader.getCgl().gl.uniform2i(this._loc, this._value[0], this._value[1]);
this.needsUpdate = false;
this._cgl.profileData.profileUniformCount++;
}
updateValue3I()
{
if (!this._value) return;
if (!this._isValidLoc())
{
this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
this._cgl.profileData.profileShaderGetUniform++;
this._cgl.profileData.profileShaderGetUniformName = this._name;
}
this._shader.getCgl().gl.uniform3i(this._loc, this._value[0], this._value[1], this._value[2]);
this.needsUpdate = false;
this._cgl.profileData.profileUniformCount++;
}
updateValue4I()
{
if (!this._isValidLoc())
{
this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
this._cgl.profileData.profileShaderGetUniform++;
this._cgl.profileData.profileShaderGetUniformName = this._name;
}
this._shader.getCgl().gl.uniform4i(this._loc, this._value[0], this._value[1], this._value[2], this._value[3]);
this._cgl.profileData.profileUniformCount++;
}
setValueI(v)
{
if (v != this._value)
{
this.needsUpdate = true;
this._value = v;
}
}
setValue2I(v)
{
if (!v) return;
if (!this._oldValue)
{
this._oldValue = [v[0] - 1, 1];
this.needsUpdate = true;
}
else if (v[0] != this._oldValue[0] || v[1] != this._oldValue[1])
{
this._oldValue[0] = v[0];
this._oldValue[1] = v[1];
this.needsUpdate = true;
}
this._value = v;
}
setValue3I(v)
{
if (!v) return;
if (!this._oldValue)
{
this._oldValue = [v[0] - 1, 1, 2];
this.needsUpdate = true;
}
else if (v[0] != this._oldValue[0] || v[1] != this._oldValue[1] || v[2] != this._oldValue[2])
{
this._oldValue[0] = v[0];
this._oldValue[1] = v[1];
this._oldValue[2] = v[2];
this.needsUpdate = true;
}
this._value = v;
}
setValue4I(v)
{
this.needsUpdate = true;
this._value = v || vec4.create();
}
updateValueBool()
{
if (!this._isValidLoc()) this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
else this.needsUpdate = false;
this._shader.getCgl().gl.uniform1i(this._loc, this._value ? 1 : 0);
this._cgl.profileData.profileUniformCount++;
}
setValueBool(v)
{
if (v != this._value)
{
this.needsUpdate = true;
this._value = v;
}
}
setValueArray4F(v)
{
this.needsUpdate = true;
this._value = v;
}
updateValueArray4F()
{
if (!this._isValidLoc()) this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
else this.needsUpdate = false;
if (!this._value) return;
this._shader.getCgl().gl.uniform4fv(this._loc, this._value);
this._cgl.profileData.profileUniformCount++;
}
setValueArray3F(v)
{
this.needsUpdate = true;
this._value = v;
}
updateValueArray3F()
{
if (!this._isValidLoc()) this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
else this.needsUpdate = false;
if (!this._value) return;
this._shader.getCgl().gl.uniform3fv(this._loc, this._value);
this._cgl.profileData.profileUniformCount++;
}
setValueArray2F(v)
{
this.needsUpdate = true;
this._value = v;
}
updateValueArray2F()
{
if (!this._isValidLoc()) this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
else this.needsUpdate = false;
if (!this._value) return;
this._shader.getCgl().gl.uniform2fv(this._loc, this._value);
this._cgl.profileData.profileUniformCount++;
}
setValueArrayF(v)
{
this.needsUpdate = true;
this._value = v;
}
updateValueArrayF()
{
if (!this._isValidLoc()) this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
else this.needsUpdate = false;
if (!this._value) return;
this._shader.getCgl().gl.uniform1fv(this._loc, this._value);
this._cgl.profileData.profileUniformCount++;
}
setValueArrayT(v)
{
this.needsUpdate = true;
this._value = v;
}
updateValue3F()
{
if (!this._value) return;
if (!this._isValidLoc())
{
this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
this._cgl.profileData.profileShaderGetUniform++;
this._cgl.profileData.profileShaderGetUniformName = this._name;
}
this._shader.getCgl().gl.uniform3f(this._loc, this._value[0], this._value[1], this._value[2]);
this.needsUpdate = false;
this._cgl.profileData.profileUniformCount++;
}
setValue3F(v)
{
if (!v) return;
if (!this._oldValue)
{
this._oldValue = [v[0] - 1, 1, 2];
this.needsUpdate = true;
}
else if (v[0] != this._oldValue[0] || v[1] != this._oldValue[1] || v[2] != this._oldValue[2])
{
this._oldValue[0] = v[0];
this._oldValue[1] = v[1];
this._oldValue[2] = v[2];
this.needsUpdate = true;
}
this._value = v;
}
updateValue2F()
{
if (!this._value) return;
if (!this._isValidLoc())
{
this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
this._cgl.profileData.profileShaderGetUniform++;
this._cgl.profileData.profileShaderGetUniformName = this._name;
}
this._shader.getCgl().gl.uniform2f(this._loc, this._value[0], this._value[1]);
this.needsUpdate = false;
this._cgl.profileData.profileUniformCount++;
}
setValue2F(v)
{
if (!v) return;
if (!this._oldValue)
{
this._oldValue = [v[0] - 1, 1];
this.needsUpdate = true;
}
else if (v[0] != this._oldValue[0] || v[1] != this._oldValue[1])
{
this._oldValue[0] = v[0];
this._oldValue[1] = v[1];
this.needsUpdate = true;
}
this._value = v;
}
updateValue4F()
{
if (!this._isValidLoc())
{
this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
this._cgl.profileData.profileShaderGetUniform++;
this._cgl.profileData.profileShaderGetUniformName = this._name;
}
if (!this._value)
{
this._log.warn("no value for uniform", this._name, this);
this._value = [0, 0, 0, 0];
}
this.needsUpdate = false;
this._shader.getCgl().gl.uniform4f(this._loc, this._value[0], this._value[1], this._value[2], this._value[3]);
this._cgl.profileData.profileUniformCount++;
}
setValue4F(v)
{
if (typeof this.value == "number") this.value = vec4.create(); // this should not be needed, but somehow it crashes with some shadermods
if (!v) return;
if (!this._oldValue)
{
this._oldValue = [v[0] - 1, 1, 2, 3];
this.needsUpdate = true;
}
else if (v[0] != this._oldValue[0] || v[1] != this._oldValue[1] || v[2] != this._oldValue[2] || v[3] != this._oldValue[3])
{
this._oldValue[0] = v[0];
this._oldValue[1] = v[1];
this._oldValue[2] = v[2];
this.needsUpdate = true;
}
this._value = v;
}
updateValueM4()
{
if (!this._isValidLoc())
{
this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
this._cgl.profileData.profileShaderGetUniform++;
this._cgl.profileData.profileShaderGetUniformName = this._name;
}
if (!this._value || this._value.length % 16 != 0) return console.log("this.name", this._name, this._value);
this._shader.getCgl().gl.uniformMatrix4fv(this._loc, false, this._value);
this._cgl.profileData.profileUniformCount++;
}
setValueM4(v)
{
this.needsUpdate = true;
this._value = v || mat4.create();
}
updateValueArrayT()
{
if (!this._isValidLoc()) this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
else this.needsUpdate = false;
if (!this._value) return;
this._shader.getCgl().gl.uniform1iv(this._loc, this._value);
this._cgl.profileData.profileUniformCount++;
}
updateValueT()
{
if (!this._isValidLoc())
{
this._loc = this._shader.getCgl().gl.getUniformLocation(this._shader.getProgram(), this._name);
this._cgl.profileData.profileShaderGetUniform++;
this._cgl.profileData.profileShaderGetUniformName = this._name;
}
this._cgl.profileData.profileUniformCount++;
this._shader.getCgl().gl.uniform1i(this._loc, this._value);
this.needsUpdate = false;
}
setValueT(v)
{
this.needsUpdate = true;
this._value = v;
}
}
Uniform.glslTypeString = (t) =>
{
if (t == "f") return "float";
if (t == "b") return "bool";
if (t == "i") return "int";
if (t == "2i") return "ivec2";
if (t == "2f") return "vec2";
if (t == "3f") return "vec3";
if (t == "4f") return "vec4";
if (t == "m4") return "mat4";
if (t == "t") return "sampler2D";
if (t == "tc") return "samplerCube";
if (t == "3f[]") return null; // ignore this for now...
if (t == "m4[]") return null; // ignore this for now...
if (t == "f[]") return null; // ignore this for now...
console.warn("[CGL UNIFORM] unknown glsl type string ", t);
};
/**
* @function setValue
* @memberof Uniform
* @instance
* @param {Number|Array|Matrix|Texture} value
*/
export { Uniform };