jfcameron / gdk-graphics

3D Rendering using OpenGLES 2.0/WebGL1.0. Platforms: Linux, Windows, Mac, x86 64bit, arm64, wasm
MIT License
1 stars 1 forks source link

shader: uniform default values, set_uniform guarding #36

Open jfcameron opened 3 years ago

jfcameron commented 3 years ago

default values

currently all values are 0 inited. im not sure if webgl supports initializing uniforms with user values. need to look into it. if not, think about how to provide initial values. collection of maps provided to the factor? e.g: factory(fragsource, vertsource, uniform_initializers).

Bigger issue: in addition to this, since there is no "default value" to assign if the material didnt assign anything, values can "leak" from one use of the shader program to another. e.g: a and b both use prog 1, a sets 1's cut off uniform value, 2 does not. user expected a to have a modified cut off and b to have the default, but in fact b will have the value set by a.

guarding

set_uniform is not guarded and rendering is done in a tight loop. so any shaders that have uniforms will have set called even if the new value is the old value. Before actually doing this though, this should be investigated. Would this actually improve performance at all?

jfcameron commented 3 years ago

the thing I dont like about this is that the source and values are separated. maybe think about a unified shader file format. I would use JSON but you cant do clean multiline strings, which I consider necessary for code. could be simply a series of {}s.

{
  float uCutOff 0.5
  vec2 uOffset 2 5
}
{
  vert code here
}
{
  frag code here
}
jfcameron commented 3 years ago

map<string, pair<optional, T>> could be added to shader class. optional would hold the custom value, second would be the default value. if first has_value at draw time then upload its value and set the option to null. if its null then upload the second. something like that

jfcameron commented 3 years ago

This is important, I ran into this while implementing translucency. I thought I had found a bug when UVs were incorrect for one of my entities if I disabled all other entities in the scene. I had forgotten to explicitly set the material's UV data, so I had been unknowingly relying on values leaking from other materials for it to look correct.

The feature is straightforward but requries refactoring/thinking. Currently Material's purpose is to act as uniform bundle state. Should the work inside mat class be separated to something else or should a shader own an internal default material?. actually that isnt a bad idea.

jfcameron commented 3 years ago

its come up again. Again I forgot to set a texture uniform for a model, this time i noticed because it used a different texture on Linux vs Windows (draw order must be different on the two platforms) I dont think a "default material" makes sense, since this needs to be available from the external interface and a material needs a shader to be built. I dont think a shaderless material should be constructable, since it cannot be used to render anything.. so its a meaningless state that would be a different source of confusion. i think the correct move is to create a new class "uniform_data", which is collection of maps that associates uniform names with values of different types (float, vec, texture, ...). This would be consistent with the existence of vertex_data, attribute_data_view, image_view, etc.