Skip to content

Conversation

@player-03
Copy link
Collaborator

This allows effect methods to share registers in a safer way. Currently, if you want to use a custom attribute, it might look like this:

Long-ish sample code
class GlowMethod extends EffectMethodBase {
	private override function createMethodVO():MethodVO {
		return new GlowMethodVO();
	}
	
	private override function getVertexCode(vo:MethodVO, regCache:ShaderRegisterCache):String {
		final vo:GlowMethodVO = cast vo;
		
		//Figure out which attributes will be used. This will later be read by `setRenderState()`.
		vo.glowColor = regCache.getFreeVertexAttribute();
		vo.glowRadius = regCache.getFreeVertexAttribute();
		
		//Figure out which varyings will be used. This will later be read by `getFragmentCode()`.
		vo.glowColorVarying = regCache.getFreeVarying();
		vo.glowRadiusVarying = regCache.getFreeVarying();
		
		return 'mov ${ vo.glowColorVarying }, ${ vo.glowColor }\n'
			+ 'mov ${ vo.glowRadiusVarying }, ${ vo.glowRadius }\n'
			+ /* other necessary code */;
	}
	
	private override function getFragmentCode(vo:MethodVO, regCache:ShaderRegisterCache, targetReg:ShaderRegisterElement):String {
		final vo:GlowMethodVO = cast vo;
		
		//Since `vo` is the same, we can access the varying values.
		final glowColor:ShaderRegisterElement = vo.glowColorVarying;
		final glowRadius:ShaderRegisterElement = vo.glowRadiusVarying;
		
		return /* glow rendering code */;
	}
	
	private override function setRenderState(vo:MethodVO, renderable:IRenderable, stage3DProxy:Stage3DProxy, camera:Camera3D):Void {
		final subGeometry:ISubGeometry = cast(renderable, SubMesh).subGeometry;
		
		if(subGeometry is MySubGeometry) {
			final vo:GlowMethodVO = cast vo;
			
			//Since `vo` is the same, we can access the attribute indices.
			(cast subGeometry:MySubGeometry).activateGlowColorBuffer(vo.glowColor.index, stage3DProxy);
			(cast subGeometry:MySubGeometry).activateGlowRadiusBuffer(vo.glowRadius.index, stage3DProxy);
		}
	}
}

class GlowMethodVO extends MethodVO {
	public var glowColor:ShaderRegisterElement = null;
	public var glowRadius:ShaderRegisterElement = null;
	
	public var glowColorVarying:ShaderRegisterElement = null;
	public var glowRadiusVarying:ShaderRegisterElement = null;
}

Here, glowRadius is an extra attribute, with extra vertex data allocated for it. GlowMethod figures out which buffer index glowRadius will be uploaded to, and it can read from that index to access the color data.

But what if a second method wants to know glowRadius? There is no good way to pass that data. VOs are never shared between methods, and nothing in either ShaderRegisterCache nor ShaderRegisterData can store a custom ShaderRegisterElement.

There are several places you could put it. You could make a static variable in GlowMethod, or make a variable in MySubGeometry, or something. But Away3D always goes out of its way not to do this. I think the concern is that if methods begin reading/writing information outside the control of ShaderCompiler, it might leak between materials.

This PR lets methods store arbitrary ShaderRegisterElements for other methods to access later. ShaderCompiler knows about this data, and clears it each time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant