Materials, passes, techniques and I somewhere at the middle

Started by
5 comments, last by NukeBird 4 years, 5 months ago

I'm making my graphics engine from scratch, at that moment I have some architecture and my engine can render PBR materials parsed from GLTF 2.0 models (embedded textures)


Here's some of my classes:

-AbstractResource (reload and validate)

-AbstractBuffer (VBO/IBO/SBO, gotta imlement CBO later (atomic counters))

-BufferLayout (description how attributes lying in VBO)

-AbstractCommand (basic command with execute() method, examples: BindShader, BindTexture2D, BindTextureCube, BindVertexArray, Draw, SetUniform<T>)

-AbstractDrawable (everything that have update(dt), generate_batch_list(model, view, proj))

-AbstractMaterial (describes how to render stuff, basically: textures, specific shader variant and way how to bind shader, uniforms and textures together in a correct way)

-Batch (all the information needed to render something using one draw call: vao, material, uniforms and some flags. Can generate CommandList via generate_command_list())

-AbstractShader (stores sources of vertex and fragment shaders + stores shader variants)

-AbstractShaderVariant (compiled shader with specific ShaderSettings)

-ShaderSettings (flags + definitions)

-AbstractTexture2D, AbstractTextureCube, AbstractSampler2D, TextureFormat, TextureType, ...

-AbstractVertexArray

-AbstractRenderPass (execute(batches), reload, validate)

-Pipeline (list of render passses)

-GAPI (using gapi we can make OpenGL objects. Basically it stores factories)

-Engine (stores GAPI, pipeline and BatchList (vector of batches, updates and flushes every frame. We can "push" batches/drawables or "flush" them (to render all the batches and clear BatchList)


Everything was good until today... Because today I started dreaming about OIT (Order Independent Transparency).

I implemented such a passes: DepthPrepass, OpaquePass, TransparentPass, and logically OIT must be somewhere inside of TransparentPass.

OIT requieres two passes:

1. Render ALL transparent fragments with disabled depth test + store depth and color of each fragment in SBO (SSBO)

2. Render again, but now with depth test. Use info from (1) to correctly mix a fragment colors


To do an OIT I need one SBO and one r32ui texture. Great, but... IT CAN'T BE PART OF MATERIAL. Why the freak material shaders should know about things requiered for OIT?

That's just weird. Yes, (1) transparent pass need to know color of each fragment, but... Ideologically AbstractMaterial should care about shading models and not about transparency ;(


I was thinking about subroutines, like I can standardize function names requiered for lighting, but..... I'm working with ES 3.1 and here I don't have any subroutines.

Also I support ES2, but in that case I can just say "ok, no OIT"


What can be done with that? I'm completely lost

Advertisement

Can one fragment shader pass color to another one?

Or shader program can have only 1 attached fragment shader?

Or can I provide entrypoint (void main) and some functions without implementations in A and implement functions from shader A in shader B?

NukeBird said:

Can one fragment shader pass color to another one?

Or shader program can have only 1 attached fragment shader?

1-no, they run in parallel, but what you can do is use derivatives ddx ddy to sample color-or any other varible- of neighbouring pixel as shaders are competent on 2*2 grids of pixels.

2- not neccessarily, depends on platform, the way it compiles and attach programs

3- My gess is you need to implement the functions unless you include them or do preprocessor magic.


Can't you have additional textures that come from other passes and are not tied to material? Then just have shader with specific branch (#ifdefs or whatever you use) that has "OIT_PASS" or something enabled and it will sample from it only then. My shaders can define what external resources they require and this enables various additional code paths in them for this purpose. Not everything has to be included in Material, especially when the resource is some full screen texture with information.

Or if you really want to encapsulate it all within material you can have OITransparencyMaterial that has additional info. I'd prefer to keep it out of materials and as additional layer that binds material info + resources generated by previous passes + specialized shader.


Where are we and when are we and who are we?
How many people in how many places at how many times?

@JohnnyCode yep, I have read that it is possible to attach multiple fragment shaders to the same shader programs, but only one of them can have void main() entry point

But even wiki says that it's a good way to get weird driver bugs. As you said, I can do some preprocessor magic and concatenate strings by myself

@noizex here's whole point - hide all these OITs, because material shouldn't care about such a stuff. Material should care only about shading of fragments. Material know everything about its shader and input textures and uniforms, basically every material can declare and implement something like vec4 shade()

yeah, passes can store textures and other stuff inside themselves, also I can connect dependent RenderPasses on setup of Pipeline

@JohnnyCode @noizex atm I'm thinking about this: every material stores fragment shader without void main() and with declared vec4 shade() function, and SOMETHING will glue such a shaders with a shader that implements all other stuff not related to material. It will just call shade() when it's required + do all the magic. +as I can see, I can have multiple SOMETHINGs on multiple passes.
By SOMETHING I mean some class that will make and execute glued shader program. I know how to implement it, but I don't know how to call such a class :(
What do you think?

This topic is closed to new replies.

Advertisement